在嵌套循环中使用预准备语句时的最佳方法

时间:2015-12-14 13:59:09

标签: java jdbc prepared-statement

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

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. 或者我该怎么办?
  5. sqls只是插入语句,两个sqls以某种方式相互关联。当我从some.params收到错误时,我不想插入一些内容。

2 个答案:

答案 0 :(得分:3)

循环中的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 - 所以首先要对某些进行所有更新(在第二个循环中) )执行 some2

的所有更新

只要你在一次交易中保留这个,你就没事了。

可能也可能保留嵌套代码 - 但是你的s1和s2的计数器是独立的,所以你真的不应该用autocommit on来做,因为没有办法告诉哪些项目已经处理,哪些没有。

在这种情况下,你最终会得到像

这样的东西
        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
        }

答案 1 :(得分:0)

将它放在私有函数中并传递参数,即sql1,some.name,some.type

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

根据条件调用具有不同参数的相同函数。