2012-04-25 67 views
0

是否有可能以某种方式混合PreparedStatement批处理和Statement批处理,并保持双方在单个事务中执行的好处?将PreparedStatement批处理与Statement批处理混合在一起,有可能吗?

我有什么是我自己的数据访问对象,它代表事务。我想用这样的:

/* here transaction starts: object receive connection, etc. */ 
MyTableTransactionObject myTable = new MyTableTransactionObject(); 

myTable.clear(); 
myTable.insert(Row1); 
myTable.insert(Row2); 
myTable.insert(Row3); 
myTable.doSomethingElse(); 
myTable.insert(Row4); 

/* here transaction ends, batches are executed changes are commited, 
    statements are closed */ 
myTable.execute(); 
myTable.close(); 

“引擎盖下” MyTableTransactionObject的有using语句或预处理语句(可能有多个预处理语句)的方法。例如:在clear()方法我想用statement.addBatch("DELETE FROM table;"),在insert(...)方法我想用特殊的PreparedStatement执行SQL INSERT操作,在doSomethingElse(...)我想用不同的PreparedStatement做别的事情,等

我怎样才能实现执行这些陈述为了他们被称为myTable.execute()

+0

如果你使用MySQL,请确保您能够在驱动程序级别rewriteBatchedStatements该解决方案使用自动提交(真实):http://dev.mysql.com/doc/refman/5.5/en /connector-j-reference-configuration-properties.html – 2012-04-26 03:13:13

回答

0

如果您的Statements/PreparedStatements共享一个公共Connection,并且您没有在该Connection上提交事务,则它们将共享一个公共事务。

+0

因此,无论我在每个addBatch()之后还是在几个addBatch()之后调用executeBatch()(假设AutoCommit设置为false),都没有什么区别? – Mixer 2012-04-25 17:55:42

+0

是正确的,就当前交易而言无关紧要。请注意,如果您调用executeBatch()的频率较低(因为您的数据库往返次数较少),您将获得更好的性能表现。 – jtahlborn 2012-04-26 11:39:18

1

这不是最优雅的解决方案,您将付出%$#的表现,但它确实有效。

public class DBEngine { 

private final int defaultBatchSize = 1000; 

private Pool pool = null; 
private Connection con = null; 
private PreparedStatement ps = null; 
private ArrayList<PreparedStatement> globalBatch = new ArrayList<PreparedStatement>(); 
private int k = 0; //bean-wide batch counter 
private boolean debugMode = false; 
private PreparedStatement batchPs = null; 
//-------------------------------- 
DBEngine(){ 
    this.pool = new Pool(); 
    this.con = pool.getConnection(); 
    this.ps = null; 
    this.k = 0; //bean-wide batch counter 
} 
//------------- 
boolean mixedBatchTime(boolean force){ 
    return mixedBatchTime(defaultBatchSize, force); 
} 
//------------- 
boolean mixedBatchTime(int customBatchSize){ 
    return mixedBatchTime(customBatchSize, false); 
} 
//------------- 
boolean mixedBatchTime(){ 
    return mixedBatchTime(defaultBatchSize, false); 
} 
//------------- 
// Executes a mixed batch of PreparedStatements 
//------------- 
boolean mixedBatchTime(int customBatchSize, boolean force){ 


    if(k > customBatchSize - 1 || force){ 
     try { 
      StringBuilder sqlStmt = new StringBuilder(); 

      for(int i = 0; i < globalBatch.size(); i++){ 
       sqlStmt.append(globalBatch.get(i) + "; "); 
      } 

      batchPs = con.prepareStatement(sqlStmt.toString());  
      batchPs.execute(); 
      ps = null; 
      sqlStmt = null; 
      batchPs = null; 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
     k = 0; 
     globalBatch = null; 
     globalBatch = new ArrayList<PreparedStatement>(); 
     return true; 
    }else return false; 

    } 
} 

你必须增加K的实际批准备部分即你用到dbengine豆喜欢里面:

//------------------------------------------ 
    boolean updateSomeQuantity(int someID, int someQuantity){ 

     try{ 
      // detects if the statement has changed in order to recompile it only once per change 
      if(ps!=null && !ps.toString().contains("UPDATE sometable SET somequantity =")){ 
       ps = null; 
       String updateStmt = "UPDATE sometable SET somequantity = ? WHERE someID = ?"; 
       ps = con.prepareStatement(updateStmt); 
      }else if(ps == null){ 
       String updateStmt = "UPDATE sometable SET somequantity = ? WHERE someID = ?"; 
       ps = con.prepareStatement(updateStmt); 
      } 

      ps.setInt(1, someQuantity) 
      ps.setInt(2, someID); 

      globalBatch.add(ps); 
      k++; // very important 

      return true; 

     } catch (SQLException e) { 
      e.printStackTrace(); 
      if(e.getNextException() != null) e.getNextException().printStackTrace(); 
      return false; 
      } 
    } 

实际的实现是另一码您实例的实例DBEngine bean,并在循环中使用updateSomeQuantity(somequantity)方法以及mixedBatchTime()方法。循环结束后,调用mixedBatchTime(true)来批处理剩余的任何内容。

注:

+0

@jtahlborn:您可以在方法重载中向bean引擎指定一个自定义的批量大小。主要问题和性能受损的地方在于,每次更改“主题”时,必须重新使用PreparedStatements来重新使用PreparedStatements。 – adv 2014-01-07 16:11:08