当前位置: 首页 > 知识库问答 >
问题:

JDBC插入批处理在SqlServer和Oracle上的工作方式不同

李经国
2023-03-14

我正在尝试在SqlServer和Oracle上进行批量插入,并在以下测试代码中实现:

public class TesteBatch {

public static void main(String[] args) throws ClassNotFoundException {

    Connection con = getConnection();
    try {
        con.setAutoCommit(false);
    } catch (SQLException e) {
        e.printStackTrace();
    }


    PreparedStatement psInsert = criaPs(con);

    Date time = Calendar.getInstance().getTime();

    for (int i = 1; i <= 50000; i++) {
        try {

            psInsert.setInt(1, i);

            psInsert.setTimestamp(2, new Timestamp(time.getTime()));
            psInsert.addBatch();
        } catch (SQLException e) {
            System.out.println("Erro inserindo " + i);
        }
    }

    try {
        int[] executeBatch = psInsert.executeBatch();
        System.out.println(Arrays.toString(executeBatch));
        psInsert.close();
        con.close();
    } catch (BatchUpdateException e) {
        e.printStackTrace();
        System.out.println(Arrays.toString(e.getUpdateCounts()));

    } catch (SQLException e) {
        e.printStackTrace();
    }

}

private static PreparedStatement criaPs(Connection con) {
    try {
        return con.prepareStatement("insert into tester values (? , ?)");
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

private static Connection getConnection() {
    try {
        String url = "jdbc:oracle:thin:@BI_ENS:1521:xe";
        Class.forName("oracle.jdbc.OracleDriver");
        return DriverManager.getConnection(url,"xxxx", "xxxx");
    } catch (ClassNotFoundException | SQLException e) {
        throw new RuntimeException(e);
    }
}

}

该代码将数据插入到具有主键ID和时间戳的Tester表中。

我想做的是以这样一种方式插入数据库:即使批处理中的一些数据已经存在,也会插入不存在的数据,因为违反了主键约束,所以会抛出BatchUpdateException。

我正在测试一个有50000个条目的批次,其中50%已经在数据库中。

使用SqlServer,它会按预期工作,抛出异常,但未复制的数据仍会插入数据库,最终所有50k注册表都在数据库中。

但是,它在Oracle上不起作用,出现异常,批处理中没有插入任何内容,甚至数据库中不存在的数据。最后,只有50%的批次在那里。

有人能解释一下为什么这会发生在Oracle上吗?有没有办法让它像在SqlServer上一样工作?

谢谢大家!

共有1个答案

卜季萌
2023-03-14

根据甲骨文文档http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraperf.htm#JJDBC28767这就是oracle处理批处理的方式:

注意:批处理的执行总是在生成错误的批处理的第一个元素时停止。

 类似资料:
  • 我正在使用hibernate jpa执行批处理更新。 更新:我得到了解决方案:问题是我正在刷新已经刷新的事务,因此它没有给我任何事务正在进行中的错误以及我上面发布的错误,所以我只是删除了`getem().flush();和getEm().clear();从finally块开始工作:)

  • 问题内容: 我需要将几亿条记录插入mysql db。我要一次插入一百万个。请在下面查看我的代码。它似乎很慢。有什么方法可以优化它吗? 问题答案: 我在mysql中遇到类似的性能问题,并通过在连接URL中设置useServerPrepStmts和rewriteBatchedStatements属性来解决。

  • 我需要使用JDBC在Oracle数据库中进行大量插入,即两位数百万。为此,我使用了类似于以下类的东西,灵感来自使用JDBC进行批处理插入的高效方法: 虽然这种插入方式很好,但速度非常慢。JDBC batch insert performance描述了MySQL基本上可以解决这个问题,因为在Oracle上似乎不存在,但在这里没有太大帮助。 为了提高性能,我还尝试将语句切换为一个大的

  • 我很难让Hibernate在MySQL上执行大容量插入。 我有要排序的主键生成类型,下面是我的dao.xml 这使得每次都可以执行单个查询。我也相应地刷新和清除实体管理器。 技术堆栈:Spring 4,Hibernate 5.2。 编辑1:我也浏览了下面的链接,但没有运气 https://vladmihalcea.com/how-to-batch-insert-and-update-stateme

  • 我需要在我的MySQL数据库中进行批量插入(近10000个)。我正在使用JPA/Hibernate和spring Boot。我从hibernate文档中读到了在hibernate中执行大容量插入/更新,我认为我的代码不能正常工作,因为它顺序地插入hibernate查询,而不是在批处理插入中执行它们。下面是我的代码。我是不是漏掉了什么? 这是我的数据源配置。 我是不是漏掉了什么? 请帮帮忙。

  • 我正在使用lambda、API网关和Dynamodb 我正在创建一个batchWrite函数,在一个函数中上载25个以上的项目 但我发现,当我上传35个项目时,前25个项目成功上传到dynamodb,但最后10个项目失败,但没有记录任何错误 该函数在node.js中编写 日志如下所示。