JDBC PreparedStatement批量继续插入错误

时间:2015-04-24 16:27:30

标签: java mysql spring jdbc weblogic

大家好我在java中创建一个带有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

数据库服务器是MySQL,在表中插入我有几个限制

当我插入生成错误时受这些限制

我想运行批处理并省略错误,此时抛出一个异常结束批处理

在创建批处理之前,我一个接一个地保存Big,如

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

但它很慢,在某些情况下,批处理产生4000项,插入1500并省略其余

如何处理批次?

修改

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

进行连接

我测试了这个属性

1

continueBatchOnError=true

2

rewriteBatchedStatements=true

3

continueBatchOnError=true
rewriteBatchedStatements=true

添加connection.setAutoCommit(false);但继续在重复项中抛出异常

修改

忘了提,我用于连接Hibernate + Spring

唯一的For-Save示例是在Hibernate中创建的,但是为了性能,我尝试使用JDBC Batch,在webapp的其他过程中也使用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();
            }

        }
    });
}

这会产生下一个例外

  

java.sql.BatchUpdateException:重复条目&#39; 1-000002725&#39;为了钥匙   &#39; masterID&#39;

但我需要继续

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

1 个答案:

答案 0 :(得分:7)

我认为可以用一个词IGNORE

来概括

使用此

运行批处理时
sb.append("INSERT IGNORE INTO `FRT_DB`.`ITEM` ");

这个不会抛出异常与约束,此传递以及行中仍有旧数据相关

如果您需要保存“新数据”,请更改INSERT ... ON DUPLICATE KEY语句,但是,现在认为不需要它。

代码@Transactional中的提交或回滚不是必需的。

您的大try {仅在SqlException中崩溃,而不是在BatchUpdateException

您只需添加allowMultiQueries beacuse other和default true

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