JDBC PreparedStatement Batch continue insert on error

Posted

技术标签:

【中文标题】JDBC PreparedStatement Batch continue insert on error【英文标题】: 【发布时间】:2015-07-03 08:50:23 【问题描述】:

你好,我在 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: 重复条目 '1-000002725' 的键 '主ID'

但我需要继续

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

【问题讨论】:

您使用的是“MySQL Connector/J”JDBC 驱动程序吗?如果是这样,默认行为应该是continueBatchOnError=true,这似乎是你想要的。 @GordThompson 我使用 weblogic 进行连接,我添加属性 continueBatchOnError=true 并重新启动,但问题仍然存在,在第一次插入时抛出异常 ps.executeBatch(); 稍后阅读此 SO post 并添加此 rewriteBatchedStatements=true 但是仍然是例外 【参考方案1】:

我觉得可以用一个词来概括IGNORE

当你用这个运行批处理时

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

这个不会抛出异常,有约束,这个传递,你的行中仍然是旧数据

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

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

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

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

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

【讨论】:

我正在使用 mssql,其中它们没有被忽略(说无效对象)。他们在 jdbcTemplate 中有任何选择吗?

以上是关于JDBC PreparedStatement Batch continue insert on error的主要内容,如果未能解决你的问题,请参考以下文章

JDBC - 语句、PreparedStatement、CallableStatement 和缓存

JDBC封装学习笔记---面向对象的JDBC,使用preparedStatement

JDBC深入理解Statement和PreparedStatement

jdbc防止sql注入-PreparedStatement

JDBC中的Statement和PreparedStatement的区别

关于JDBC预处理功能PreparedStatement