zoukankan      html  css  js  c++  java
  • 使用JDBC对数据库实现批处理操作

      本篇讲述如何使用JDBC对数据库实现批处理操作。很多时候单条SQL命令不能满足我们的需求,我们需要对数据库一次实现很多操作,需要发送一批SQL命令给数据库执行。

      而JDBC也提供了相应的方法给我们实现批处理操作。分别使用Statement对象或者PreparedStatement对象。这两种方式分别有着不同的运用场景:

      ⑴ 使用Statement对象

         优点:能发送多条不同操作类型的SQL命令,也就是说在这发送的一批SQL语句中可以有各种增删改查命令。

         缺点:虽然能发送多条不同操作类型的SQL命令,但没有预编译,因此在数据库这一批中的每条SQL都需要编译和执行两个步骤。

      ⑵ 使用PreparedStatement对象

         优点:发送的是预编译后的SQL语句,数据库对这一批SQL命令只需要执行这一个步骤即可。

         缺点:只能发送多条相同操作类型,但占位符参数可以不同的SQL命令。也就是说这一批SQL要么是更新,要么是添加等等。稍后会介绍。

     

    操作:

      ① 无论是Statement对象还是PreparedStatement对象,内部都含有一个List集合来保存一批多条SQL语句。两个对象都使用addBatch方法来添加每一条SQL语句(Statement使用有参的addBatch方法,PreparedStatement使用无参的addBatch方法,后面会介绍到)。

      ② 当Statement对象或PreparedStatement对象都添加完一批SQL之后,都使用executeBatch()方法来使数据库执行批处理,完成后返回一个整型数组int[],该整型数组中的元素的顺序对应于提交给Statement对象或PreparedStatement对象的SQL语句顺序,如果返回的是大于或等于0的数则表示成功处理并给出执行所影响的行数。当然改数组还会是别的内容,具体请看相关API文档:

      

      ③ 在每次执行完executeBatch()方法后,请一定要再调用clearBatch()方法,将清空Statement对象或PreparedStatement对象中List集合保存的SQL命令列表。

      ④ 在使用批处理操作时,且不可一次执行过多SQL命令,例如几千万次,尤其是在使用PreparedStatement对象的方式情况下,极容易造成程序内存溢出。对于要执行过多次的操作,请将执行次数再分成各小批分别执行。

      下面分别以使用Statement对象和使用PreparedStatement对象的两个例子来说明两种批处理方式的不同之处。

    例1:使用Statement对象进行批处理

      在这个案例中,我使用Statement对象进行批处理操作同时包含了插入和修改两种操作,如果该批处理成功执行就说明了使用Statement对象能进行不同类型的数据库操作。

    创建数据库和表:

    create database jdbcdemo;
             
        use jdbcdemo;
             
        create table batchtest (
             id int primary key,
             name varchar(40)
        )

    创建工程,在工程中导入数据库连接驱动的jar包。在【src】目录下新建一个database.properties文件,内容如下:

        driver=com.mysql.jdbc.Driver
        url=jdbc:mysql://localhost:3306/jdbcdemo
        username=root
        password=root

      构建JDBC的工具类,包括注册驱动,获取连接,释放资源和连接等,这部分同《JDBC操作数据库的学习(2)》中相同,此处略。

    使用Statement对象进行批处理操作:

     1 public void statementbatch() throws SQLException {
     2         Connection conn = null;
     3         Statement st = null;
     4         ResultSet rs = null;
     5         
     6         try{
     7             conn = JdbcUtils.getConnection();
     8             st = conn.createStatement();
     9             String sql1 = "insert into batchtest(id,name) values(1,'Ding')";
    10             String sql2 = "update batchtest set name='LRR' where id=1 ";
    11 
    12             st.addBatch(sql1);
    13             st.addBatch(sql2);
    14 
    15             st.executeBatch();
    16             st.clearBatch();                    
    17         }finally{
    18             JdbcUtils.release(conn, st, rs);
    19         }
    20     }
    View Code

    查看数据库执行情况:

      

      第一条SQL是插入命令,插入一个id列为1,name列为“Ding”的行数据项;第二条SQL是修改命令,将id列为1的行数据项的name列修改为“LRR”。

    例2:使用PreparedStatement对象进行批处理

      因为PreparedStatement对象只能执行相同的操作类型,因此在该案例中我向数据库中执行插入的批处理SQL。

    创建数据库和表(与例1相同):

    create database jdbcdemo;
             
        use jdbcdemo;
             
        create table batchtest (
             id int primary key,
             name varchar(40)
        )

    创建工程,在工程中导入数据库连接驱动的jar包。在【src】目录下新建一个database.properties文件,内容如下:

        driver=com.mysql.jdbc.Driver
        url=jdbc:mysql://localhost:3306/jdbcdemo
        username=root
        password=root

    构建JDBC的工具类,包括注册驱动,获取连接,释放资源和连接等,这部分同《JDBC操作数据库的学习(2)》中相同,此处略。

    使用PreparedStatement对象进行批处理操作:

     1 public void preparedStatementBatch() throws SQLException {
     2         Connection conn = null;
     3         PreparedStatement st = null;
     4         ResultSet rs = null;
     5         
     6         try{
     7             conn = JdbcUtils.getConnection();
     8             String sql = "insert into batchtest(id,name) values(?,?)";
     9             st = conn.prepareStatement(sql);
    10             
    11             st.setInt(1, 1);    //设置id列
    12             st.setString(2, "Ding");   //设置name列
    13             st.addBatch();
    14             
    15             st.setInt(1, 2);    //设置id列
    16             st.setString(2, "LRR");   //设置name列
    17             st.addBatch();
    18             
    19             st.executeBatch();
    20             st.clearBatch();            
    21         }finally{
    22             JdbcUtils.release(conn, st, rs);
    23         }
    24     }
    View Code

    查看数据库执行情况:

      

      可以看到使用PreparedStatement对象只能对同一条SQL语句中的占位符替代不同参数的批处理操作。

      正是基于这样的设计,使我们可以利用循环,对一些具有循环性质的替代占位符的参数使用PreparedStatement对象进行批处理,还是上面的例2 ,先清空batchtest表,其他不变,就改变程序为:

     1 public void preparedStatementBatch() throws SQLException {
     2         Connection conn = null;
     3         PreparedStatement st = null;
     4         ResultSet rs = null;
     5         
     6         try{
     7             conn = JdbcUtils.getConnection();
     8             String sql = "insert into batchtest(id,name) values(?,?)";
     9             st = conn.prepareStatement(sql);
    10             
    11             for(int i=1;i<=5;i++) {
    12                 st.setInt(1, i);     //设置id列
    13                 st.setString(2, "a"+i);   //设置name列
    14                 st.addBatch();
    15             }
    16             
    17             st.executeBatch();
    18             st.clearBatch();            
    19         }finally{
    20             JdbcUtils.release(conn, st, rs);
    21         }
    22     }
    View Code

    查看数据库执行情况:

      

      对于每次循环,都将在调用addBatch方法后将占位符已经被替代为参数的SQL语句存入PreparedStatement对象中的集合里,在下一次循环就可以进行新的占位符替代并再次存入新的SQL语句,存入SQL语句的次数和循环次数相关,因此如果循环次数过大,那么按上面的例子也将会导致程序内存溢出,解决方法就是将循环次数再分成小的循环批次一批一批地执行。

      

    解决:

      

      基本到此就将使用JDBC操作数据库进行批处理介绍完毕,通常我们会使用PreparedStatement对象的方式多一些,同时最后再说明一点,以上的案例我们都是使用的是MySQL数据库,对于大数据量的批处理操作,MySQL数据库的执行相比Oracle数据库的速度来说还差的很多,因此如果要对数据库执行大量的批处理操作,建议使用Oracle数据库。

     

     

     

                  

  • 相关阅读:
    LR12_IE11报错,闪退
    loadrunner11无法启动IE9
    启动数据库失败
    测试代码
    python中的JSON(1)
    文件和异常(二)
    文件和异常(一)
    类(三)
    类(二)
    初识类(一)
  • 原文地址:https://www.cnblogs.com/fjdingsd/p/5272888.html
Copyright © 2011-2022 走看看