JDBC PreparedStatement Batch continue insert on error

JDBC PreparedStatement Batch continue insert on error

你好,我在 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,在table中插入我有几个限制

由于这些限制,我在插入时产生了错误

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

在我创建批次之前我有一个大的保存一个一个喜欢

//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 批处理,在 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: Duplicate entry '1-000002725' for key 'masterID'

但我需要继续

spring + 休眠设置会干扰 jdbc 的属性?我不知道

我觉得一个字可以概括IGNORE

当你运行批次

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

不会抛出异常 与约束相关,这会过去,并且您的行中仍然是旧数据

如果您需要保存 'new data' 则更改为 INSERT ... ON DUPLICATE KEY 语句,但是,现在认为不需要它。

您的代码中不需要提交或回滚 @Transactional 适合您。

你的大 try { 只在 SqlException 中崩溃,而不是在 BatchUpdateException

中崩溃

您只需要添加 allowMultiQueries 因为其他和默认 true

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