【问题标题】:Best way when using prepared statement in nested loop在嵌套循环中使用准备好的语句时的最佳方式
【发布时间】:2015-12-14 13:59:08
【问题描述】:

在嵌套循环中执行多个查询时,最好的方法是什么?我有如下代码:

String sql1 = SQLContainer.SOME_SQL;
String sql2 = SQLContainer.SOME_SQL2;
    if (someThings != null) {
        for (Some some : someThings) {
            ps = con.prepareStatement(sql1);
            ps.setString(1, some.name);
            ps.setString(2, some.type);
            ps.executeUpdate();

            if (some.getParams != null) {
                for (Some2 some2 : some.params) {
                    ps = con.prepareStatement(sql2);
                    ps.setString(1, some2.name);
                    ps.setString(2, some2.value);
                    ps.setString(3, some2.type);
                    ps.executeUpdate();
                }
            }
        }
    }
  1. 这样使用可以吗?
  2. 我应该创建 2 个不同的循环,一个用于 sql1,一个用于 sql2?
  3. 我应该为不同的循环创建 2 种不同的方法吗?
  4. 或者我该怎么办?

sqls 只是插入语句,两个 sqls 以某种方式相互关联。当我也从 some.params 收到错误时,我不想插入一些。

【问题讨论】:

    标签: java jdbc prepared-statement


    【解决方案1】:

    除非你做对了,否则循环中的 SQL 性能会很差。

    在您的情况下,我强烈建议使用批处理 SQL

    第一个循环看起来像这样:

        int p1Count = 0;
        int BATCHSIZE = 1000;
        if (something) {
                PreparedStatement ps1 = con.prepareStatement(SQLContainer.SOME_SQL);        
                for (Some some : someThing) {
                    ps1.setString(1, some.name);
                    ps1.setString(2, some.type);
                    ps1.addBatch();
                    if(++p1Count % BATCHSIZE == 0) {
                        ps1.executeBatch();
                    }
                    ... 
                }
                ps1.executeBatch();
    

    同样,您应该拆分循环以一次执行 一种 SQL - 所以首先对 some 执行所有更新,然后(在第二个循环中) 为 some2

    做所有更新

    只要您将其保留在一笔交易中,就可以了。

    可以也可能保留嵌套代码 - 但是您的 s1 和 s2 计数器将是独立的,因此您真的不应该在启用自动提交的情况下这样做,因为没有办法告诉您哪些项目已处理,哪些未处理。

    在这种情况下,你最终会得到类似的东西

            int p1Count = 0;
            int p2Count = 0;
            int BATCHSIZE = 1000;
            if (something) {
                try(PreparedStatement ps1 = con.prepareStatement(SQLContainer.SOME_SQL);
                       PreparedStatement ps2 = con.prepareStatement(SQLContainer.SOME_SQL2)) {                      
                  for (Some some : someThing) {
                    ps1.setString(1, some.name);
                    ps1.setString(2, some.type);
                    ps1.addBatch();
                    if(++p1Count % BATCHSIZE == 0) {
                        ps1.executeBatch();
                    }
                    if (somethingElse) {
                        for (Some2 some2 : some.param) {
                            ps2.setString(1, some2.name);
                            ps2.setString(2, some2.value);
                            ps2.setString(3, some2.type);
                            ps2.addBatch();
                            if(++p2Count % BATCHSIZE == 0) {
                                ps2.executeBatch();
                            }
                        }
                    }
                  }
                  p2.executeBatch();
                  p1.executeBatch();
                } //End try-with-resource
            }
    

    【讨论】:

      【解决方案2】:

      把它放在一个私有函数中并传递参数,即sql1、some.name、some.type

      ps = con.prepareStatement(sql1);
      ps.setString(1, some.name);
      ps.setString(2, some.type);
      ps.executeUpdate();
      

      根据条件调用不同参数的同一个函数。

      【讨论】:

      • Sqls和参数不同。我更新了代码和问题。是的,我可以制作不同的方法,但为什么会更好?
      猜你喜欢
      • 1970-01-01
      • 2022-01-23
      • 2020-08-13
      • 1970-01-01
      • 2012-07-07
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多