PreparedStatement 批量更新,插入数据到Oracle mysql

时间:2022-09-21 16:56:35
  1. /**   
  2.  * 更新数据库已有的customer信息   
  3.  * @param List<CustomerBean>   
  4.  * @return    
  5.  */    
  6. public int updateExistsInfo(List<CustomerBean> updateList){    
  7.     //查询的SQL语句    
  8.     String sql = "update t_customer set LICENSE_KEY=?,CORPORATE_NAME=?,INTEGRATED_CLASSIFICATION=?,BOSSHEAD=?," +    
  9.             "CONTACT_PHONE=?,ORDER_FREQUENCY=?,CONTACT_ADDRESS=?,USER_ID=? where CUSTOMER_ID=?" ;        
  10.     //插入需要的数据库对象    
  11.     Connection conn = null;    
  12.     PreparedStatement pstmt = null;    
  13.     
  14.     try  {              
  15.         conn = new DBSource().getConnection();    
  16.         //设置事务属性    
  17.         conn.setAutoCommit(false);      
  18.         pstmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);                
  19.         for(CustomerBean cbean : updateList){    
  20.             pstmt.setString(1, cbean.getLicense_key());    
  21.             pstmt.setString(2, cbean.getCorporate_name());    
  22.             pstmt.setString(3, cbean.getIntegrated_classification());    
  23.             pstmt.setString(4, cbean.getBosshead());    
  24.             pstmt.setString(5, cbean.getContact_phone());    
  25.             pstmt.setString(6, cbean.getOrder_frequency());    
  26.             pstmt.setString(7, cbean.getContact_address());    
  27.             pstmt.setInt   (8, cbean.getUser_id());    
  28.             pstmt.setInt   (9, cbean.getCustomer_id());    
  29.                 
  30.             pstmt.addBatch();    
  31.                 
  32.         }    
  33.         int[] tt = pstmt.executeBatch();    
  34.         System.out.println("update : " + tt.length);    
  35.     
  36.         //提交,设置事务初始值    
  37.         conn.commit();    
  38.         conn.setAutoCommit(true);    
  39.     
  40.         //插入成功,返回    
  41.         return tt.length;    
  42.     
  43.     }catch(SQLException ex){    
  44.         try{    
  45.             //提交失败,执行回滚操作    
  46.             conn.rollback();    
  47.     
  48.         }catch (SQLException e) {    
  49.             e.printStackTrace();    
  50.             System.err.println("updateExistsInfo回滚执行失败!!!");    
  51.         }    
  52.     
  53.         ex.printStackTrace();    
  54.         System.err.println("updateExistsInfo执行失败");    
  55.     
  56.         //插入失败返回标志0    
  57.         return 0;    
  58.     
  59.     }finally {    
  60.         try{    
  61.             //关闭资源    
  62.             if(pstmt != null)pstmt.close();    
  63.             if(conn != null)conn.close();    
  64.                 
  65.         }catch (SQLException e) {    
  66.             e.printStackTrace();    
  67.             System.err.println("资源关闭失败!!!");    
  68.         }    
  69.     }    
  70. }     
  71.     
  72. /**   
  73.  * 插入数据中没有的customer信息   
  74.  * @param List<CustomerBean>   
  75.  * @return    
  76.  */    
  77. public int insertNewInfo(List<CustomerBean> insertList){    
  78.                 
  79.     //查询的SQL语句    
  80.     String sql = "insert into t_customer(CUSTOMER_ID," +    
  81.             "LICENSE_KEY,CORPORATE_NAME,INTEGRATED_CLASSIFICATION,BOSSHEAD,CONTACT_PHONE," +    
  82.             "ORDER_FREQUENCY,CONTACT_ADDRESS,USER_ID,CUSTOMER_NUM,CUSTOMER_CODING," +    
  83.             "INVESTIGATION_TIME,SMS_REC_FLAG,WAP_FLAG,PRICE_GATHERING_FLAG,SOCIETY_STOCK_FLAG," +    
  84.             "REGION_TYPE)" +    
  85.             "VALUES(CUSTOMER.NEXTVAL," +    
  86.             "?,?,?,?,?," +    
  87.             "?,?,?,?,?," +    
  88.             "TO_DATE(?,'YYYY-MM-DD'),?,0,0,0," +    
  89.             "?)" ;    
  90.         
  91.     //插入需要的数据库对象    
  92.     Connection conn = null;    
  93.     PreparedStatement pstmt = null;    
  94.     
  95.     try  {              
  96.         conn = new DBSource().getConnection();    
  97.     
  98.         //设置事务属性    
  99.         conn.setAutoCommit(false);    
  100.             
  101.         pstmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);                
  102.     
  103.         for(CustomerBean cbean : insertList){    
  104.             pstmt.setString(1, cbean.getLicense_key());    
  105.             pstmt.setString(2, cbean.getCorporate_name());    
  106.             pstmt.setString(3, cbean.getIntegrated_classification());    
  107.             pstmt.setString(4, cbean.getBosshead());    
  108.             pstmt.setString(5, cbean.getContact_phone());    
  109.             pstmt.setString(6, cbean.getOrder_frequency());    
  110.             pstmt.setString(7, cbean.getContact_address());    
  111.             pstmt.setInt(8, cbean.getUser_id());    
  112.             pstmt.setString(9"gyyc00000");//    
  113.             pstmt.setString(10"95000000");//    
  114.             pstmt.setString(11, getToday());    
  115.             pstmt.setInt(12, cbean.getSms_rec_flag());    
  116.             pstmt.setInt(13, cbean.getRegion_type());    
  117.                 
  118.     
  119.             pstmt.addBatch();    
  120.     
  121.         }    
  122.         int[] tt = pstmt.executeBatch();    
  123.         System.out.println("insert : " + tt.length);    
  124.     
  125.         //提交,设置事务初始值    
  126.         conn.commit();    
  127.         conn.setAutoCommit(true);    
  128.     
  129.         //插入成功,返回    
  130.         return tt.length;    
  131.     
  132.     }catch(SQLException ex){    
  133.         try{    
  134.             //提交失败,执行回滚操作    
  135.             conn.rollback();    
  136.     
  137.         }catch (SQLException e) {    
  138.             e.printStackTrace();    
  139.             System.err.println("insertNewInfo回滚执行失败!!!");    
  140.         }    
  141.     
  142.         ex.printStackTrace();    
  143.         System.err.println("insertNewInfo执行失败");    
  144.     
  145.         //插入失败返回标志0    
  146.         return 0;    
  147.     
  148.     }finally {    
  149.         try{    
  150.             //关闭资源    
  151.             if(pstmt != null)pstmt.close();    
  152.             if(conn != null)conn.close();    
  153.                 
  154.         }catch (SQLException e) {    
  155.             e.printStackTrace();    
  156.             System.err.println("资源关闭失败!!!");    
  157.         }    
  158.     }    
  159. }    
         使用Java JDBC基本的API批量插入数据到数据库中
         
  1. import java.sql.Connection;  
  2. import java.sql.Statement;  
  3. //...  
  4. Connection connection = new getConnection();  
  5. Statement statemenet = connection.createStatement();  
  6. for (Employee employee: employees) {  
  7.     String query = "insert into employee (name, city) values('"  
  8.             + employee.getName() + "','" + employee.getCity + "')";  
  9.     statemenet.addBatch(query);  
  10. }  
  11. statemenet.executeBatch();  
  12. statemenet.close();  
  13. connection.close();  
  14. 请注意我们是如何从Employee对象中的数据动态创建查询并在批处理中添加,插入一气呵成。完美!是不是?
    等等......你必须思考什么关于SQL注入?这样动态创建的查询SQL注入是很容易的。并且每个插入查询每次都被编译。
    为什么不使用PreparedStatement而不是简单的声明。是的,这是个解决方案。下面是SQL注入安全批处理。
    SQL Injection Safe Batch - SQL注入安全批处理
    思考一下下面代码:
    [java]  view plain  copy
    1. import java.sql.Connection;  
    2. import java.sql.PreparedStatement;  
    3.  //...  
    4. String sql = "insert into employee (name, city, phone) values (?, ?, ?)";  
    5. Connection connection = new getConnection();  
    6. PreparedStatement ps = connection.prepareStatement(sql);  
    7.  for (Employee employee: employees) {  
    8.     ps.setString(1, employee.getName());  
    9.     ps.setString(2, employee.getCity());  
    10.     ps.setString(3, employee.getPhone());  
    11.     ps.addBatch();  
    12. }  
    13. ps.executeBatch();  
    14. ps.close();  
    15. connection.close();  
    看看上面的代码。漂亮。我们使用的java.sql.PreparedStatement和在批处理中添加INSERT查询。这是你必须实现批量插入逻辑的解决方案,而不是上述Statement那个。
    这一解决方案仍然存在一个问题。考虑这样一个场景,在您想要插入到数据库使用批处理上万条记录。嗯,可能产生的OutOfMemoryError:

    java.lang.OutOfMemoryError: Java heap space
    com.mysql.jdbc.ServerPreparedStatement$BatchedBindValues.<init>(ServerPreparedStatement.java:72)
    com.mysql.jdbc.ServerPreparedStatement.addBatch(ServerPreparedStatement.java:330)
    org.apache.commons.dbcp.DelegatingPreparedStatement.addBatch(DelegatingPreparedStatement.java:171)

    这是因为你试图在一个批次添加所有语句,并一次插入。最好的办法是将执行分批次。看看下面的解决方案
    Smart Insert: Batch within Batch - 智能插入:将整批分批
    这是一个简单的解决方案。考虑批量大小为1000,每1000个查询语句为一批插入提交。
    [java]  view plain  copy
    1. String sql = "insert into employee (name, city, phone) values (?, ?, ?)";  
    2. Connection connection = new getConnection();  
    3. PreparedStatement ps = connection.prepareStatement(sql);  
    4. final int batchSize = 1000;  
    5. int count = 0;  
    6. for (Employee employee: employees) {  
    7.     ps.setString(1, employee.getName());  
    8.     ps.setString(2, employee.getCity());  
    9.     ps.setString(3, employee.getPhone());  
    10.     ps.addBatch();  
    11.     if(++count % batchSize == 0) {  
    12.         ps.executeBatch();  
    13.     }  
    14. }  
    15. ps.executeBatch(); // insert remaining records  
    16. ps.close();  
    17. connection.close();  
        这才是理想的解决方案,它避免了SQL注入和内存不足的问题。看看我们如何递增计数器计数,一旦BATCHSIZE 达到 1000,我们调用executeBatch()提交。