2015-04-24 66 views
8

你好家伙我在Java中创建一个PreparedStatement批这样JDBC的PreparedStatement批继续插上错误

for(Item item: list){ 
    ps.setString(1, item.getSome()); 
    ps.setString(2, item.getFoo()); 
    ps.setString(3, item.getBatman()); 
    statement.addBatch(); 

    if (++count % batchSize == 0) { 
     results = ps.executeBatch(); //execute parcial batch 

     if (results != null) 
      System.out.println(results.length); 
    } 

} 
results= ps.executeBatch(); //execute rest of batch 

的DATEBASE服务器是一个MySQL,在表中插入我有几个限制

通过当我插入这些限制产生的错误

我想运行批处理和忽略错误,在这一刻抛出一个异常的结束批次

之前,我创建批处理我有一个很大的节省一个个像

//seudocode level 
For item 
Try{ 
    insert item 
}catch(E){nothing happens} 

但它是非常缓慢的,在某些情况下,该批次procces 4000项,插入1500和省略其余

如何处理批次?

编辑

我使用WebLogic使conections与此驱动程序mysql-connector-java-commercial-5.0.3-bin

我测试这个特性

1.

continueBatchOnError=true 

2.

rewriteBatchedStatements=true 

3.

continueBatchOnError=true 
rewriteBatchedStatements=true 

并添加connection.setAutoCommit(false);而是继续扔在重复

编辑例外

忘了提,我使用Hibernate的连接+春

唯一For-Save示例在Hibernate中进行,但为了提高性能,我尝试在Web中的其他过程中使用JDBC Batch应用程序也使用JDBC与Hibernate的连接,效果很好

这是完整的代码

@Transactional 
public void saveMany(final List<Item> items) { 
    getMySqlSession().doWork(new Work() { 
     @Override 
     public void execute(Connection connection) throws SQLException { 

      StringBuilder sb = new StringBuilder(); 
      sb.append("INSERT INTO `FRT_DB`.`ITEM` "); 
      sb.append("("); 
      sb.append("`masterID`, "); 
      sb.append("`agent`, "); 
      sb.append("`rangeID`) "); 
      sb.append("VALUES "); 
      sb.append("("); 
      sb.append("?, "); 
      sb.append("?, "); 
      sb.append("?) "); 

      int[] results = null; 

      PreparedStatement ps = null; 

      try { 
       connection.setAutoCommit(false); 
       ps = connection.prepareStatement(sb.toString()); 


       final int batchSize = 250; 
       int count = 0; 

       for (Item item : items) { 

        if (item.getMasterId() != null) { 
         ps.setInt(1, item.getMasterId()); 
        } else 
         ps.setNull(1, java.sql.Types.INTEGER); 

        if (item.getAgent() != null) { 
         ps.setString(2, item.getAgent()); 
        } else 
         ps.setNull(2, Types.VARCHAR); 

        if (item.getRangeId() != null) 
         ps.setInt(3, item.getRangeId()); 
        else 
         ps.setNull(3, Types.INTEGER); 

        ps.addBatch(); 

        if (++count % batchSize == 0) { 
         results = ps.executeBatch(); 

         if (results != null) 
          System.out.println(results.length); 

        } 

       } 

       results= ps.executeBatch(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

     } 
    }); 
} 

这产生一个Exception

java.sql.BatchUpdateException:重复的项目“1-000002725 “关键 'masterID'

但我需要继续

spring + hibernate设置干扰jdbc的属性?我不知道

+0

是否使用了 “MySQL的连接器/ J” JDBC驱动程序?如果是这样,默认行为应该是'continueBatchOnError = true',这似乎是你想要的。 –

+0

@GordThompson我使用weblogic进行连接,我添加了属性'continueBatchOnError = true'并重新启动,但是问题仍然存在于第一次插入中'ps.executeBatch();'稍后读取[SO post](http:// stackoverflow .com/questions/26307760/mysql-and-jdbc-with-rewritebatchedstatements-true)并添加'rewriteBatchedStatements = true',但仍然是异常 – jasilva

回答

6

我觉得可以用一个词IGNORE

当您运行这个

sb.append("INSERT IGNORE INTO `FRT_DB`.`ITEM` "); 

批这不会抛出与约束realted一个异常概括起来,这个传过来,并且您的行中仍旧有旧数据

如果您需要保存'新数据',请更改为INSERT ... ON DUPLICATE KEY声明,但现在认为不需要它。

提交或回滚并不需要在您的代码@Transactional为您工作。

你大try {只在SQLEXCEPTION崩溃不是的BatchUpdateException

你只需要添加allowMultiQueries怎么一回事,因为其他和默认true

http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html

+0

适合我! – jasilva