JavaWeb了解之入门篇3(JDBC操作数据库)

目录

  1. 基本使用
  2. 事务
  3. 批处理
  4. LOB(Large Objects,大型对象)大数据

安装好数据库后,应用是不能直接使用数据库的,需要通过相应的数据库驱动程序去和数据库打交道。SUN公司为了统一、简化对数据库的操作,定义了一套Java操作数据库的接口规范JDBC(Java Data Base Connectivity)。JDBC接口的具体实现(即数据库驱动程序)由各数据库厂商去完成,开发人员只需调用JDBC,JDBC会加载具体的驱动去操作对应的数据库。
因此,开发JDBC应用需要导入相应的数据库驱动依赖包。

1. 基本使用(以mysql数据库为例)

下载mysql-connector-java-8.0.11.jar(mysql数据库驱动), 选Platform Indepentdent。放入WEB-INF的lib目录下

注意:
  1. mysql8.0及之后的版本的数据库连接由com.mysql.jdbc.Driver更换为com.mysql.cj.jdbc.Driver,且需要显式关闭SSL连接和指定CST。
  1. 示例(简单使用)
  1. 创建数据库、表、插入数据
在终端输入sql语句:
create database test character set utf8 collate utf8_general_ci;
use Test;
create table users(
    id int primary key,
    name varchar(40),
    password varchar(40),
    email varchar(60),
    birthday date
);
insert into users(id,name,password,email,birthday) values(1,'zhansan','123456','[email protected]','2220-12-04');
insert into users(id,name,password,email,birthday) values(2,'lisi','123456','[email protected]','2222-12-04');
insert into users(id,name,password,email,birthday) values(3,'wangwu','123456','[email protected]','2222-12-04');
可使用Navicat Premium可视化工具(localhost  3306  root  数据库密码) 连接本地数据库查看数据库中的数据。
  1. 创建数据库操作类
  package com.sst.cx;
  import java.sql.Connection;
  import java.sql.DriverManager;
  import java.sql.ResultSet;
  import java.sql.Statement;
  public class TestJSDBCModel {
       public static void main(String[] args) throws Exception {
            // 1. 加载驱动
            // 推荐使用这种方式来加载驱动
            Class.forName("com.mysql.jdbc.Driver"); 
            
            // 2.1  设置 要连接的数据库URL
            String url = "jdbc:mysql://localhost:3306/test";
            // 2.2 设置 连接的数据库时使用的用户名
            String username = "root";
            // 2.3 设置 连接的数据库时使用的密码
            String password = "密码";
            // 2.4 获取 与数据库的链接
            Connection conn = DriverManager.getConnection(url, username, password);
            // 3. 获取 用于向数据库发送sql语句的statement
            Statement st = conn.createStatement();
            
            // -----------增-----------
            String insertSql = "insert into user(….) values(…..) "; 
            int num = st.executeUpdate(insertSql);
            if(num>0){
                System.out.println("插入成功!!!");
            }
            // -----------删-----------
            String sql = "delete from user where id=1"; 
            int deleNum = st.executeUpdate(sql);
            if(deleNum>0){
                System.out.println("删除成功!!!");
            }
            // -----------改-----------
            String updateSql = "update user set name='' where name=''"; 
            int updateNum = st.executeUpdate(updateSql);
            if(updateNum>0){
                System.out.println("修改成功!!!");
            }
            // -----------查-----------
            String querySql = "select id,name,password,email,birthday from users";
            // 4. 向数据库发送sql语句,并获取代表结果集的resultset
            ResultSet rs = st.executeQuery(querySql);
            // 5. 取出结果集中的数据
            while(rs.next()){
                // 获取 字段值
                System.out.println("id=" + rs.getObject("id"));
                System.out.println("name=" + rs.getObject("name"));
                System.out.println("password=" + rs.getObject("password"));
                System.out.println("email=" + rs.getObject("email"));
                System.out.println("birthday=" + rs.getObject("birthday"));
            }
            // 6. 关闭链接,释放资源
            // 释放资源代码应放在finally语句中,以确保一定会执行)
            rs.close();
            st.close();
            conn.close();  
        }
  }

使用到的类

1. DriverManager(用来加载驱动、创建与数据库的连接)
  1. DriverManager.registerDriver(new com.mysql.jdbc.Driver()) 
    加载数据库驱动(不推荐使用该方式来加载驱动,推荐使用Class.forName("com.mysql.jdbc.Driver");灵活性高)
      1. 通过Driver的源码可知,这种方式会导致驱动程序注册两次(在内存中会有两个Driver对象)。
      2. 程序依赖mysql的API,脱离mysql的jar包,程序将无法编译。切换底层数据库将会非常麻烦。
  2. DriverManager.getConnection(url, user, password)  
    获取与数据库的链接

2. 数据库URL
  协议:子协议://主机:端口号/数据库名?参数名:参数值
  用于标识数据库的类型和位置。
  说明:
    协议固定为jdbc,子协议为各数据库规定的协议名。
    主机、端口号分别为服务器的ip地址和端口号。
  常用数据库URL:
    1. Oracle数据库:jdbc:oracle:thin:@localhost:1521:test
    2. SqlServer数据库:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=test
    3. MySql数据库:jdbc:mysql://localhost:3306/test(连接本地数据库且端口为3306时,可简写为:jdbc:mysql:///test)     

3. Connection类(代表与数据库的链接)最重要的一个对象
  如果Connection不能及时正确关闭,极易导致系统宕机。应尽量晚创建早释放。
  1. createStatement():创建向数据库发送sql语句的Statement对象。
  2. prepareStatement(sql) :创建向数据库发送预编译sql语句的PreparedStatement对象(避免了Statement对象的SQL注入问题、频繁编译SQL造成数据库缓存溢出问题)。PreparedStatement对象可对SQL进行预编译从而提高执行效率,对于sql中的参数允许使用占位符的形式进行替换从而简化了sql语句的编写。
  3. prepareCall(sql):创建执行存储过程的callableStatement对象。
  4. setAutoCommit(boolean autoCommit):设置事务是否自动提交。
  5. commit() :在此链接上提交事务。
  6. rollback() :在此链接上回滚事务。

4. Statement类(用于向数据库发送sql语句)
  1. executeQuery(String sql) :用于向数据发送查询语句(返回ResultSet结果集)。
  2. executeUpdate(String sql):用于向数据库发送insert、update或delete语句,返回一个整数(数据库中有几行数据发生变化)。
  3. execute(String sql):用于向数据库发送任意sql语句。
  4. addBatch(String sql) :把多条sql语句放到一个批处理中。
  5. executeBatch():向数据库发送一批sql语句执行。

5. ResultSet类(存储了SQL语句的执行结果)
  采用类似表格的方式封装执行结果。维护了一个指向表格数据行的游标,初始时游标在第一行之前。
  1. 获取数据
    // 获取任意类型的数据
    getObject(int index)
    getObject(string columnName)
    // 获取指定类型的数据
    getString(int index)
    getString(String columnName)
    ...
  2. 操作结果集
    1. next():移动到下一行
    2. Previous():移动到前一行
    3. absolute(int row):移动到指定行
    4. beforeFirst():移动resultSet的最前面。
    5. afterLast() :移动到resultSet的最后面。
可能遇到的错误:
1. java.lang.UnsupportedClassVersionError。解决:
  换jdk版本为高版本即可(MyEclipse|设置|Java|JRE换jdk版本)。
  1. 示例(规范使用)

第1步. 创建db.properties

在src下创建db.properties文件,内容如下:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=密码

第2步. 创建数据库处理类

package com.sst.cx;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JdbcUtils {
    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;
    static{
        try{
            // 读取db.properties文件中的数据库连接信息
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties prop = new Properties();
            prop.load(in);
            // 获取数据库连接驱动
            driver = prop.getProperty("driver");
            // 获取数据库连接URL地址
            url = prop.getProperty("url");
            // 获取数据库连接用户名
            username = prop.getProperty("username");
            // 获取数据库连接密码
            password = prop.getProperty("password");
            // 加载数据库驱动
            Class.forName(driver);
        }catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
    // 获取数据库连接对象
    public static Connection getConnection() throws SQLException{
        return DriverManager.getConnection(url, username,password);
    }
    // 释放资源:Connection数据库连接对象、负责执行SQL命令的Statement对象、存储查询结果的ResultSet对象
    public static void release(Connection conn,Statement st,ResultSet rs){
        if(rs!=null){
            try{
                rs.close();  // 关闭存储查询结果的ResultSet对象
            }catch (Exception e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(st!=null){
            try{
                st.close();   // 关闭负责执行SQL命令的Statement对象
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try{
                conn.close();  // 关闭Connection数据库连接对象
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

第3步. 使用

package com.sst.cx;
import java.sql.*;
public class TestJdbcM {
    public static void main(String[] args){
        (new TestJdbcM()).insert();
    }
    // 增
    public void insert(){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            // 获取一个数据库连接
            conn = JdbcUtils.getConnection();
            // 通过conn对象创建负责执行SQL命令的Statement对象
            st = conn.createStatement();
            // 要执行的SQL命令
            String sql = "insert into users(id,name,password,email,birthday) values(6,'ss','123','[email protected]','2222-02-02')";
            // 执行插入操作,executeUpdate方法返回成功的条数
            int num = st.executeUpdate(sql);
            if(num>0){
                System.out.println("插入成功!!");
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            // SQL执行完成之后释放相关资源
            JdbcUtils.release(conn, st, rs);
        }
    }
    // 删
    public void delete(){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "delete from users where id=3";
            st = conn.createStatement();
            int num = st.executeUpdate(sql);
            if(num>0){
                System.out.println("删除成功!!");
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    // 改
    public void update(){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "update users set name='hello',email='[email protected]' where id=3";
            st = conn.createStatement();
            int num = st.executeUpdate(sql);
            if(num>0){
                System.out.println("更新成功!!");
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    // 查
    public void find(){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "select * from users where id=3";
            st = conn.createStatement();
            rs = st.executeQuery(sql);
            if(rs.next()){
                System.out.println(rs.getString("name"));
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
}

第3步. 另一种使用方式 (占位符)

public class JdbcCRUDByPreparedStatement {
  // 增   
  public void insert(){
    Connection conn = null;
    PreparedStatement st = null;
    ResultSet rs = null;
    try{
        // 获取一个数据库连接
        conn = JdbcUtils.getConnection();
        // 要执行的SQL命令,SQL中的参数使用?作为占位符
        String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)";
        // 通过conn对象获取负责执行SQL命令的prepareStatement对象
        st = conn.prepareStatement(sql);
        // 为SQL语句中的参数赋值,注意,索引是从1开始的
        /**
        * SQL语句中各个字段的类型如下:
        *  +----------+-------------+
        | Field    | Type        |
        +----------+-------------+
        | id       | int(11)     |
        | name     | varchar(40) |
        | password | varchar(40) |
        | email    | varchar(60) |
        | birthday | date        |
        +----------+-------------+
        */
        st.setInt(1, 1);    //    id是int类型的
        st.setString(2, "hello");// name是varchar(字符串类型)
        st.setString(3, "123");// password是varchar(字符串类型)
        st.setString(4, "[email protected]");// email是varchar(字符串类型)
        st.setDate(5, new java.sql.Date(new Date().getTime()));// birthday是date类型
        int num = st.executeUpdate();  // 执行插入操作,executeUpdate方法返回成功的条数
        if(num>0){
           System.out.println("插入成功!!");
        }
        }catch (Exception e) {
             e.printStackTrace();
        }finally{
             JdbcUtils.release(conn, st, rs);  // SQL执行完成之后释放相关资源
        }
}
// 删
public void delete(){
   Connection conn = null;
   PreparedStatement st = null;
   ResultSet rs = null;
   try{
       conn = JdbcUtils.getConnection();
       String sql = "delete from users where id=?";
       st = conn.prepareStatement(sql);
       st.setInt(1, 1);
       int num = st.executeUpdate();
       if(num>0){
           System.out.println("删除成功!!");
       }
   }catch (Exception e) {
       e.printStackTrace();
   }finally{
       JdbcUtils.release(conn, st, rs);
   }
}
// 改
public void update(){
   Connection conn = null;
   PreparedStatement st = null;
   ResultSet rs = null;
   try{
       conn = JdbcUtils.getConnection();
       String sql = "update users set name=?,email=? where id=?";
       st = conn.prepareStatement(sql);
       st.setString(1, "hello");
       st.setString(2, "[email protected]");
       st.setInt(3, 2);
       int num = st.executeUpdate();
       if(num>0){
           System.out.println("更新成功!!");
       }
   }catch (Exception e) {
       e.printStackTrace();
   }finally{
       JdbcUtils.release(conn, st, rs);
   }
}
// 查
public void find(){
   Connection conn = null;
   PreparedStatement st = null;
   ResultSet rs = null;
   try{
       conn = JdbcUtils.getConnection();
       String sql = "select * from users where id=?";
       st = conn.prepareStatement(sql);
       st.setInt(1, 1);
       rs = st.executeQuery();
       if(rs.next()){
           System.out.println(rs.getString("name"));
       }
   }catch (Exception e) {
   }finally{
       JdbcUtils.release(conn, st, rs);
   }
}
}

获取数据库自动生成的主键

sql
  create table test{
     id int primary key auto_increment,
     name varchar(20)
  } 
代码
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
          String sql = "insert into test(name) values(?)";
          st = conn.prepareStatement(sql);
          st.setString(1, "zhangsan");
          st.executeUpdate();
          // 获取数据库自动生成的主键
          rs = st.getGeneratedKeys();
          if(rs.next()){
            System.out.println(rs.getInt(1));
          }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }

示例(JSTL标签)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.io.*,java.util.*,java.sql.*"%>
<%@ page import="javax.servlet.http.*,javax.servlet.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>



JDBC


    <%--
        JDBC驱动名、数据库 URL、数据库的用户名与密码
        useUnicode=true&characterEncoding=utf-8 防止中文乱码
     --%>
    

    <%-- 插入数据
    
        INSERT INTO website (NAME,url,age,country) VALUES ('京东', 'https://www.jd.com/', 15, 'CN');
     --%>

    <%-- 删除website表中id为9数据
    
    
         DELETE FROM website WHERE id = ?
         
    --%>

    <%-- 修改website表中id为8数据
    
    
         UPDATE website SET name="biancheng" WHERE id = ?
         
    --%>

    <%-- 查询数据 --%>
    
        SELECT * from website;
    

    
            
id name url age country

2. 事务

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。

  1. 概念
1. 原子性(Atomicity)  
  原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败。
2. 一致性(Consistency)
  事务必须使数据库从一个一致性状态变换到另外一个一致性状态。以转账为例子,A向B转账,假设转账之前这两个用户的钱加起来总共是2000,那么A向B转账之后,不管这两个账户怎么转,A用户的钱和B用户的钱加起来的总额还是2000,这个就是事务的一致性。
3. 隔离性(Isolation)
  事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
4. 持久性(Durability)
  持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

隔离性详解

事务的隔离级别 
  多个线程开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个线程在获取数据时的准确性。
 
事务不考虑隔离性可能会引发的问题:
  1、脏读
    脏读指一个事务读取了另外一个事务未提交的数据。
    这是非常危险的,假设A向B转帐100元,对应sql语句如下所示
      1. update account set money=money+100 where name='B';
      2. update account set money=money-100 where name='A';
   当第1条sql执行完,第2条还没执行(A未提交时),如果此时B查询自己的帐户,就会发现自己多了100元钱。如果A等B走后再回滚,B就会损失100元。
  2、不可重复读
    不可重复读指在一个事务内读取表中的某一行数据,多次读取结果不同。
  3、虚读(幻读)
    虚读(幻读)是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。

MySQL数据库定义了四种事务隔离级别: 
  1. Read uncommitted(最低级别),会引发脏读、不可重复读、虚读。
   A窗口
     set transaction isolation level  read uncommitted;--设置A用户的数据库隔离级别为Read uncommitted(读未提交)
     start transaction;--开启事务
     select * from account;--查询A账户中现有的钱,转到B窗口进行操作
     select * from account--发现a多了100元,这时候A读到了B未提交的数据(脏读)
   B窗口
     start transaction;--开启事务
     update account set money=money+100 where name='A';--不要提交,转到A窗口查询
  2. Read committed时,会引发不可重复读和虚读,但避免了脏读
   A窗口
     set transaction isolation level  read committed;
     start transaction;
     select * from account;--发现a帐户是1000元,转到b窗口
     select * from account;--发现a帐户多了100,这时候,a读到了别的事务提交的数据,两次读取a帐户读到的是不同的结果(不可重复读)
   B窗口
     start transaction;
     update account set money=money+100 where name='aaa';
     commit;--转到a窗口
  3. Repeatable read(mysql默认级别)时,会引发虚读,但避免了脏读、不可重复读。
   A窗口
     set transaction isolation level repeatable read;
     start transaction;
     select * from account;--发现表有4个记录,转到b窗口
     select * from account;--可能发现表有5条记录,这时候发生了a读取到另外一个事务插入的数据(虚读)
   B窗口
     start transaction;
     insert into account(name,money) values('ggg',1000);
     commit;--转到a窗口
  4. Serializable时,会避免所有问题。
   A窗口
     set transaction isolation level Serializable;
     start transaction;
     select * from account;--转到b窗口
   B窗口
     start transaction;
     insert into account(name,money) values('ggg',1000);--发现不能插入,只能等待a结束事务才能插入

 终端查询MySQL当前事务隔离级别:select @@tx_isolation
 MySQL默认事务隔离级别:Repeatable read(可重复读)
 MySQL设置事务隔离级别:set transaction isolation level 隔离级别名
  1. 使用事务
/* 终端下在MySQL数据库中使用事务。
// 开启事务
start transaction;
// 执行语句列表...
// 回滚(在捕获到异常后)会回滚之前执行的sql语句。
rollback;
// 提交事务(未提交时关闭终端,之前执行的sql语句并不会被持久化到数据库中)
commit;
*/
代码中通过JDBC使用事务
  1. 开启事务(禁止自动提交,默认情况下执行后会立即向数据库提交SQL)
    conn.setAutoCommit(false);
  2. 手动回滚事务(执行SQL语句时出现异常后会自动回滚,也可以手动回滚)
    conn.rollback();
  3. 提交事务
    conn.commit();

手动设置事物回滚点
  // 设置事务回滚点(在有可能发生异常的SQL语句前设置)
  sp = conn.setSavepoint();
在捕获到异常中+
  // 回滚到设置的事务回滚点(之前的SQL语句是没问题的,回滚后要提交事务)
  conn.rollback(sp);
  // 回滚之后,通知数据库提交正常的SQL部分。
  conn.commit();

示例

public void testTransaction1(){
     Connection conn = null;
     PreparedStatement st = null;
     ResultSet rs = null;
     try{
       conn = JdbcUtils.getConnection();
       conn.setAutoCommit(false);// 通知数据库开启事务(start transaction)
       String sql1 = "update account set money=money-100 where name='A'";
       st = conn.prepareStatement(sql1);
       st.executeUpdate();
       String sql2 = "update account set money=money+100 where name='B'";
       st = conn.prepareStatement(sql2);
       st.executeUpdate();
       conn.commit(); // 提交事务
       System.out.println("成功!!!");  
     }catch (Exception e) {
       e.printStackTrace();
     }finally{
       JdbcUtils.release(conn, st, rs);
     }
 }

3. 批处理

开发项目时,有时需要向数据库发送一批SQL语句执行,这时应避免向数据库一条条的发送执行,而应采用JDBC的批处理机制,以提升执行效率。
JDBC实现批处理有两种方式:Statement 和 Preparedstatement。

  1. Statement完成批处理
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
          conn = JdbcUtils.getConnection();
          st = conn.createStatement();
          // 1. 添加要批量执行的SQL
          st.addBatch(sql1);
          st.addBatch(sql2);
          // 2. 执行批处理SQL语句
          st.executeBatch();
          // 3. 清除批处理命令
          st.clearBatch();
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
优点:
  1. 可以向数据库发送多条不同的SQL语句。
缺点:
  1. SQL语句没有预编译。
  2. 当向数据库发送仅参数不同的多条SQL语句时,需重复写上很多条SQL语句。
  1. PreparedStatement完成批处理
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
          String sql = "insert into testbatch(id,name) values(?,?)";
          st = conn.prepareStatement(sql);
          for(int i=1;i<1000008;i++){  // i=1000  2000
              st.setInt(1, i);
              st.setString(2, "aa" + i);
              st.addBatch();
              if(i%1000==0){
                  st.executeBatch();
                  st.clearBatch();
              }
          }
          st.executeBatch();
          st.clearBatch();
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
优点:
  1. 发送的是预编译后的SQL语句,执行效率高。
缺点:
  1. 只能应用在SQL语句相同 但 参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入或更新数据。

4. LOB(Large Objects,大型对象)大数据

LOB类型的字段现在用得越来越多了。因为这种类型的字段容量大,且一个表中可以有多个这种类型的字段,很灵活,适用于数据量非常大的业务领域(如图象、档案等)。

分为2类:
  1. clob用于存储大文本。
  2. blob用于存储二进制数据(如:图像、声音、二进制文等)。
  1. MySQL
blob存储二进制,分为:
  TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB
Text存储大文本(MySQL没有clob),分为:
  TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT

大文本

1. 添加(向数据库写入大文本---Text类型数据)
  PreparedStatement.setCharacterStream(index, reader, length); // length长度必须设置且为int型
2. 获取(从数据库中读取大文本)
  方式1 reader = resultSet.getCharacterStream(String columnLabel);
  方式2 string s = resultSet.getString(String columnLabel);
例:
sql语句 
  create table testclob(
         id int primary key auto_increment,
         hello_content text
  );
添加
    public void add(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        Reader reader = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "insert into testclob(hello_content) values(?)";
            st = conn.prepareStatement(sql);
            // 这种方式获取的路径,其中的空格会被使用“%20”代替。需调用replaceAll方法将“%20”再替换回空格。
            String path = JdbcOperaClob.class.getClassLoader().getResource("data.txt").getPath();
            path = path.replaceAll("%20", " ");
            File file = new File(path);
            reader = new FileReader(file);
            st.setCharacterStream(1, reader,(int) file.length()); 
            int num = st.executeUpdate();
            if(num>0){
                System.out.println("插入成功!!");
            }
            // 关闭流
            reader.close();
         }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
读取 
    public void read(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
          conn = JdbcUtils.getConnection();
          String sql = "select hello_content from testclob where id=1";
          st = conn.prepareStatement(sql);
          rs = st.executeQuery();
          //
          String contentStr ="";
          String content = "";
          if(rs.next()){
              // 使用resultSet.getString("字段名")获取大文本数据的内容
              content = rs.getString("hello_content");
              // 使用resultSet.getCharacterStream("字段名")获取大文本数据的内容
              Reader reader = rs.getCharacterStream("hello_content");
              char buffer[] = new char[1024];
              int len = 0;
              FileWriter out = new FileWriter("下载路径");
              while((len=reader.read(buffer))>0){
                contentStr += new String(buffer);
                out.write(buffer, 0, len);
              }
              out.close();
              reader.close();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }

二进制

1. 添加(向数据库写入二进制数据)
  PreparedStatement.setBinaryStream(i, inputStream, length);
2. 获取(从数据库中读取二进制数据)
  方式1 
    InputStream in  = resultSet.getBinaryStream(String columnLabel);
  方式2 
    InputStream in  = resultSet.getBlob(String columnLabel).getBinaryStream(); 
例:
sql
  create table testblob(
      id int primary key auto_increment,
      hello_image longblob
  );
添加
    public void add(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
          conn = JdbcUtils.getConnection();
          String sql = "insert into testblob(hello_image) values(?)";
          st = conn.prepareStatement(sql);
          // 这种方式获取的路径,其中的空格会被使用“%20”代替,需调用replaceAll方法将“%20”再替换回空格。
          String path = JdbcOperaBlob.class.getClassLoader().getResource("01.jpg").getPath();
          path = path.replaceAll("%20", " ");
          File file = new File(path);
          FileInputStream fis = new FileInputStream(file);// 生成的流
          st.setBinaryStream(1, fis,(int) file.length());
          int num = st.executeUpdate();
          if(num>0){
              System.out.println("插入成功!!");
          }
          fis.close();
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
读取
    public void read() {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "select hello_image from testblob where id=?";
            st = conn.prepareStatement(sql);
            st.setInt(1, 1);
            rs = st.executeQuery();
            if (rs.next()) {
                // 或InputStream in = rs.getBlob("image").getBinaryStream();
                InputStream in = rs.getBinaryStream("image");
                int len = 0;
                byte buffer[] = new byte[1024];
                FileOutputStream out = new FileOutputStream("下载路径");
                while ((len = in.read(buffer)) > 0) {
                  out.write(buffer, 0, len);
                }
                in.close();
                out.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
  1. Oracle
sql
     CREATE TABLE TEST_CLOB ( ID NUMBER(3), CLOBCOL CLOB);
     CREATE TABLE TEST_BLOB ( ID NUMBER(3), BLOBCOL BLOB);
db.properties(src目录下创建)
     oracleDb_Driver=oracle.jdbc.driver.OracleDriver
     oracleDb_Url=jdbc:oracle:thin:@localhost:1521:test
     oracleDb_UserName=hello
     oracleDb_Password=hello
数据库处理类
 public class JdbcUtils {
     private static String oracleDb_Driver = null;
     private static String oracleDb_Url = null;
     private static String oracleDb_UserName = null;
     private static String oracleDb_Password = null;
     static{
         try{
         // 读取db.properties文件中的数据库连接信息
         InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
         Properties prop = new Properties();
         prop.load(in);
         // 获取数据库连接驱动
         oracleDb_Driver = prop.getProperty("oracleDb_Driver");
         // 获取数据库连接URL地址
         oracleDb_Url = prop.getProperty("oracleDb_Url");
         // 获取数据库连接用户名
         oracleDb_UserName = prop.getProperty("oracleDb_UserName");
         // 获取数据库连接密码
         oracleDb_Password = prop.getProperty("oracleDb_Password");
         // 加载数据库驱动
         Class.forName(oracleDb_Driver);
         }catch (Exception e) {
           throw new ExceptionInInitializerError(e);
         }
   }
    // 获取Oracle数据库连接对象
    public static Connection getOracleConnection() throws SQLException{
        return DriverManager.getConnection(oracleDb_Url, oracleDb_UserName,oracleDb_Password);
    }
    // 释放资源:Connection数据库连接对象、负责执行SQL命令的Statement对象、存储查询结果的ResultSet对象
    public static void release(Connection conn,Statement st,ResultSet rs){
        if(rs!=null){
            try{
                // 关闭存储查询结果的ResultSet对象
                rs.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(st!=null){
            try{
                // 关闭负责执行SQL命令的Statement对象
                st.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try{
                // 关闭Connection数据库连接对象
                conn.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

CLOB数据(大文本)

public class JdbcOperaOracleClob {
  // 添加(向数据库中插入大文本)
  public void clobInsert() throws Exception {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    conn = JdbcUtils.getOracleConnection();
    boolean defaultCommit = conn.getAutoCommit();
    // 开启事务,设定不自动提交
    conn.setAutoCommit(false);
    try {
        // 插入一个空的CLOB对象
        String sql = "INSERT INTO TEST_CLOB VALUES (?, EMPTY_CLOB())";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        stmt.executeUpdate();
        // 查询此CLOB对象并锁定
        sql = "SELECT CLOBCOL FROM TEST_CLOB WHERE ID=? FOR UPDATE";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        rs = stmt.executeQuery();
        if (rs.next()) {
            // 取出此CLOB对象
            oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
            // 向CLOB对象中写入数据
            BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
            // 这种方式获取的路径,其中的空格会被使用“%20”代替,需调用replaceAll方法将“%20”再替换回空格。
            String path = JdbcOperaClob.class.getClassLoader().getResource("data.txt").getPath();
            path = path.replaceAll("%20", " ");
            BufferedReader in = new BufferedReader(new FileReader(path));
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
            in.close();
            out.close();
        }
        // 正式提交
        conn.commit();
        System.out.println("插入成功");
    } catch (Exception ex) {
        // 出错回滚
        conn.rollback();
        throw ex;
    }finally{
        // 恢复原提交状态
        conn.setAutoCommit(defaultCommit);
        JdbcUtils.release(conn,stmt,rs);
    }
  }

  // 读取(从数据库中读取大文本)
  public void clobRead() throws Exception {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    conn = JdbcUtils.getOracleConnection();
    boolean defaultCommit = conn.getAutoCommit();
    conn.setAutoCommit(false);
    try {
        // 查询CLOB对象
        String sql = "SELECT * FROM TEST_CLOB WHERE ID=?";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        rs = stmt.executeQuery();
        if (rs.next()) {
            // 获取CLOB对象
            oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
            // 以字符形式输出
            BufferedReader in = new BufferedReader(clob.getCharacterStream());
            BufferedWriter out = new BufferedWriter(new FileWriter("下载路径"));
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
            out.close();
            in.close();
        }
    } catch (Exception ex) {
        conn.rollback();
        throw ex;
    }finally{
        // 恢复原提交状态
        conn.setAutoCommit(defaultCommit);
        JdbcUtils.release(conn,stmt,rs);
    }
}

// 修改CLOB对象(是在原CLOB对象基础上进行覆盖式的修改)
public void clobModify() throws Exception {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    conn = JdbcUtils.getOracleConnection();
    boolean defaultCommit = conn.getAutoCommit();
    // 开启事务
    conn.setAutoCommit(false);
    try {
        // 查询CLOB对象并锁定
        String sql = "SELECT CLOBCOL FROM TEST_CLOB WHERE ID=? FOR UPDATE";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        rs = stmt.executeQuery();
        if (rs.next()) {
            // 获取此CLOB对象
            oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
            // 进行覆盖式修改
            BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
            // 这种方式获取的路径,其中的空格会被使用“%20”代替,需调用replaceAll方法将“%20”再替换回空格。
            String path = JdbcOperaClob.class.getClassLoader().getResource("data2.txt").getPath();
            path = path.replaceAll("%20", " ");
            BufferedReader in = new BufferedReader(new FileReader(path));
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
            in.close();
            out.close();
        }
        // 提交事务
        conn.commit();
    } catch (Exception ex) {
        // 出错回滚事务
        conn.rollback();
        throw ex;
    }finally{
        // 恢复原提交状态
        conn.setAutoCommit(defaultCommit);
        JdbcUtils.release(conn,stmt,rs);
    }
}

// 替换CLOB对象(将原CLOB对象清除,换成一个全新的CLOB对象)
public void clobReplace() throws Exception {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    conn = JdbcUtils.getOracleConnection();
    boolean defaultCommit = conn.getAutoCommit();
    // 开启事务
    conn.setAutoCommit(false);
    try {
        // 清空原CLOB对象
        String sql = "UPDATE TEST_CLOB SET CLOBCOL=EMPTY_CLOB() WHERE ID=?";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        stmt.executeUpdate();
        
        // 查询CLOB对象并锁定
        sql = "SELECT CLOBCOL FROM TEST_CLOB WHERE ID=? FOR UPDATE";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        rs = stmt.executeQuery();
        if (rs.next()) {
            // 获取此CLOB对象
            oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
            // 更新数据
            BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
            // 这种方式获取的路径,其中的空格会被使用“%20”代替,需调用replaceAll方法将“%20”再替换回空格。
            String path = JdbcOperaClob.class.getClassLoader().getResource("db.properties").getPath();
            path = path.replaceAll("%20", " ");
            BufferedReader in = new BufferedReader(new FileReader(path));
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
            in.close();
            out.close();
        }
        // 正式提交
        conn.commit();
    } catch (Exception ex) {
        // 出错回滚
        conn.rollback();
        throw ex;
    } finally {
        // 恢复原提交状态
        conn.setAutoCommit(defaultCommit);
        JdbcUtils.release(conn, stmt, rs);
    }
}
}

BLOB数据(二进制)

  Oracle定义了一个BLOB字段用于保存二进制数据,但这个字段并不能存放真正的二进制数据,只能向这个字段存一个指针,然后把数据放到指针所指向的Oracle的LOB段中, LOB段是在数据库内部表的一部分。因而在操作Oracle的Blob之前,必须获得指针(定位器)才能进行Blob数据的读取和写入。
  获得表中的Blob指针: 可以先使用insert语句向表中插入一个空的blob(调用oracle的函数empty_blob()),这将创建一个blob的指针,然后再把这个empty的blob的指针查询出来,这样就可得到BLOB对象,从而读写blob数据了。
   1、插入空blob:insert into testblob(id,image) values(?,empty_blob())
   2、获得blob的指针:
        // 注意: 必须加for update锁定该行,直至该行被修改完毕,可保证不产生并发冲突。
     select image from testblob where id=? for update 
     Blob b = rs.getBlob("image");
   3、利用io和获取到的cursor指针往数据库读写数据
   注意:以上操作需开启事务。
public class JdbcOperaOracleBlob {
  // 添加(向数据库中插入二进制数据)
  public void blobInsert() throws Exception {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    boolean defaultCommit = true;
    try {
        conn = JdbcUtils.getOracleConnection();
        // 得到数据库事务处理的默认提交方式
        defaultCommit = conn.getAutoCommit();
        // 1、开启事务
        conn.setAutoCommit(false);
        // 2、插入一个空的BLOB对象
        String sql = "INSERT INTO TEST_BLOB VALUES (?, EMPTY_BLOB())";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        stmt.executeUpdate();
        // 3、查询此BLOB对象并锁定。
        // 注意: 必须加for update锁定该行,直至该行被修改完毕,可保证不产生并发冲突。
        sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=? FOR UPDATE";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        rs = stmt.executeQuery();
        if (rs.next()) {
            // 4、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
            oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
            // 5、使用IO向BLOB对象中写入数据
            BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
            BufferedInputStream in = new BufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("01.jpg"));
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
            in.close();
            out.close();
        }
        // 6、提交事务
        conn.commit();
    } catch (Exception ex) {
        // 7、出错回滚事务
        conn.rollback();
        throw ex;
    } finally {
        // 8、恢复数据库事务处理的默认提交方式
        conn.setAutoCommit(defaultCommit);
        // 释放资源
        JdbcUtils.release(conn, stmt, rs);
    }
 }

 // 修改BLOB对象(是在原BLOB对象基础上进行覆盖式的修改)
 public void blobModify() throws Exception {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    boolean defaultCommit = true;
    try {
        conn = JdbcUtils.getOracleConnection();
        // 得到数据库事务处理的默认提交方式
        defaultCommit = conn.getAutoCommit();
        // 1、开启事务
        conn.setAutoCommit(false);
        // 2、查询此BLOB对象并锁定。注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突
        String sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=? FOR UPDATE";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        rs = stmt.executeQuery();
        if (rs.next()) {
            // 3、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
            oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
            // 4、使用IO向BLOB对象中写入数据
            BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
            BufferedInputStream in = new BufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("02.jpg"));
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
            in.close();
            out.close();
        }
        // 5、提交事务
        conn.commit();
    } catch (Exception ex) {
        // 6、出错回滚事务
        conn.rollback();
        throw ex;
    } finally {
        // 8、恢复数据库事务处理的默认提交方式
        conn.setAutoCommit(defaultCommit);
        // 释放资源
        JdbcUtils.release(conn, stmt, rs);
    }
 }

 // 替换BLOB对象(将原BLOB对象清除,换成一个全新的BLOB对象)
 public void blobReplace() throws Exception {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    boolean defaultCommit = true;
    try {
        conn = JdbcUtils.getOracleConnection();
        // 得到数据库事务处理的默认提交方式
        defaultCommit = conn.getAutoCommit();
        // 1、开启事务
        conn.setAutoCommit(false);
        // 2、清空原BLOB对象
        String sql = "UPDATE TEST_BLOB SET BLOBCOL=EMPTY_BLOB() WHERE ID=?";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        stmt.executeUpdate();
        // 3、查询此BLOB对象并锁定。注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突
        sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=? FOR UPDATE";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        rs = stmt.executeQuery();
        if (rs.next()) {
            // 4、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
            oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
            // 5、使用IO向BLOB对象中写入数据
            BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
            BufferedInputStream in = new BufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("01.jpg"));
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
            in.close();
            out.close();
        }
        // 6、提交事务
        conn.commit();
    } catch (Exception ex) {
        // 7、出错回滚事务
        conn.rollback();
        throw ex;
    } finally {
        // 8、恢复数据库事务处理的默认提交方式
        conn.setAutoCommit(defaultCommit);
        // 释放资源
        JdbcUtils.release(conn, stmt, rs);
    }
 }

 // 读取(从数据库表中读取二进制数据)
 public void blobRead() throws Exception {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    boolean defaultCommit = true;
    try {
        conn = JdbcUtils.getOracleConnection();
        // 得到数据库事务处理的默认提交方式
        defaultCommit = conn.getAutoCommit();
        // 1、开启事务
        conn.setAutoCommit(false);
        // 2、查询BLOB对象
        String sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=?";
        stmt = conn.prepareStatement(sql);
        stmt.setInt(1, 1);
        rs = stmt.executeQuery();
        if (rs.next()) {
            // 3、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
            oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
            // 4、以二进制流的形式输出
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("下载路径"));
            BufferedInputStream in = new BufferedInputStream(blob.getBinaryStream());
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
            in.close();
            out.close();
        }
        // 5、提交事务
        conn.commit();
    } catch (Exception ex) {
        // 6、出错回滚事务
        conn.rollback();
        throw ex;
    } finally {
        // 8、恢复数据库事务处理的默认提交方式
        conn.setAutoCommit(defaultCommit);
        // 释放资源
        JdbcUtils.release(conn, stmt, rs);
    }
 }
}
通过JDBC操纵Oracle数据库的LOB字段,不外乎插入、修改、替换、读取四种方式。
和其它类型字段的不同点: 
  1、必须取消自动提交。
    存取操作开始前,必须用setAutoCommit(false)取消自动提交。
    其它类型字段则无此特殊要求。这是因为存取LOB类型字段时,通常要进行多次操作可以完成。不这样的话,Oracle将抛出“读取违反顺序”错误。
  2、插入方式不同。
    LOB数据不能象其它类型数据一样直接插入(INSERT)。插入前必须先插入一个空的LOB对象,CLOB类型 的空对象为EMPTY_CLOB(),BLOB类型的空对象为EMPTY_BLOB()。之后通过SELECT命令查询得到先前插入的记录并锁定,继而将 空对象修改为所要插入的LOB对象。
  3、修改方式不同。
    其它类型的字段修改时,用UPDATE … SET…命令即可。
    而LOB类型字段,则只能用SELECT … FOR UPDATE命令将记录查询出来并锁定,然后才能修改。且修改也有两种改法:一是在原数据基础上的修改(即覆盖式修改),执行SELECT … FOR UPDATE后再改数据;二是替换(先将原数据清掉,再修改),先执行UPDATE命令将LOB字段值设为空的LOB对象,然后进行第一种改法。建议使 用替换的方法,以实现与其它字段UPDATE操作后一样的效果。
  4、存取时应使用由数据库JDBC驱动程序提供的LOB操作类。
    对于Oracle数据库,应使用oracle.sql.CLOB和oracle.sql.BLOB。不使用由数据库JDBC驱动程序提供的LOB类时,程序运行时易于出现“抽象方法调用”的错误,这是因为JDBC所定义的java.sql.Clob与 java.sql.Blob接口,其中的一些方法并未在数据库厂家提供的驱动程序中真正实现。
  5、存取手段与文件操作相仿。
    对于BLOB类型,应用InputStream/OutputStream类,此类不进行编码转换,逐个字节存取。oracle.sql.BLOB类相应提供了getBinaryStream()和getBinaryOutputStream()两个方法,前一个 方法用于读取Oracle的BLOB字段,后一个方法用于将数据写入Oracle的BLOB字段。
   对于CLOB类型,应用Reader/Writer类,此类进行编码转换。oracle.sql.CLOB类相应 提供了getCharacterStream()和getCharacterOutputStream()两个方法,前一个方法用于读取Oracle的 CLOB字段,后一个方法用于将数据写入Oracle的CLOB字段。
 
为了大幅提高程序执行效率,对BLOB/CLOB字段的读写操作,应该使用缓冲操作类(带 Buffered前缀,如:BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter)。

你可能感兴趣的:(JavaWeb了解之入门篇3(JDBC操作数据库))