首页 > 解决方案 > 在保持代码干净的同时重用准备好的语句的最佳实践?

问题描述

TL;DR:在Java中重用对象的推荐方法是什么PreparedStatement,而不会使代码混乱?


我有这样的方法:

PreparedStatement psQuery = conn.prepareStatement("select ...");
PreparedStatement psChild = conn.prepareStatement("select ... where parent = ? and ...");
ResultSet rsQuery = psQuery.executeQuery();
while (rsQuery.next()) {
    psChild.setInt(1, rsQuery.getInt("id"));
    psChild.executeQuery();
    ...
}

我先创建两个preparedStatement,然后在每次需要执行那些特定的 SQL 查询时重用它们。我没有psChild在我的循环中定义,因为那样我会在每次迭代中创建一个新的准备好的语句,而不是仅仅重用它。

现在,我的代码要复杂得多。我实际上使用了 13 个不同preparedStatement的实例,代码分布在几百行中。我非常想把它分成不同的方法,但我不知道如何正确地做到这一点。我可以想到两个选择。第一个就像我现在正在做的那样,只是分成方法:

PreparedStatement psQuery = conn.prepareStatement("select ...");
PreparedStatement psChild = conn.prepareStatement("select ... where parent = ? and ...");
ResultSet rsQuery = psQuery.executeQuery();
while (rsQuery.next()) {
    processChildren(rsQuery.getInt("id"), psChild);
}

问题是,我最终得到了processChildren这个签名:

private static void processChild(
    ...,
    final PreparedStatement psFoo,
    final PreparedStatement psBar,
    final PreparedStatement psDoc,
    final PreparedStatement psGrumpy,
    final PreparedStatement psHappy,
    final PreparedStatement psSleepy,
    final PreparedStatement psDopey,
    final PreparedStatement psBashful,
    final PreparedStatement psSneezy,
    final PreparedStatement psYetAnotherOne,
    final PreparedStatement psAndAnotherOne,
    final PreparedStatement psLastOne,
    ...) {

不太好。

另一种选择是在我需要的方法中创建每个准备好的语句。那会更干净,但这与在循环中创建它们相同:我不会重用它们。

还有另一种选择,将变量声明为类属性,这样我可以先创建它们,然后重用它们,而无需弄乱“子方法”签名。但这感觉更加错误,就像使用全局变量一样。更糟糕的是,13 个“全局”变量都具有相同的类和非常相似的名称。我不会那样做的!

我该如何继续?

注意:我知道更好的持久性解决方案,例如 JPA。我不是在寻找准备好的陈述的替代品,我只想知道在像我这样的情况下通常的方法是什么。


编辑:似乎我过度简化了我的例子。这更接近我需要做的事情:

  1. 从数据库 1 中检索所有记录。
  2. 对于它们中的每一个(第一个循环):
  3. 检查它是否存在于另一个数据库中 2.
  4. 如果没有,请在数据库 2 中创建它,然后:
  5. 从数据库 1 中检索所有子项。
  6. 对于每个孩子(第二个循环):
  7. 检查数据库 2 中是否存在子项。
  8. 如果没有,则插入它。

所以我有两层嵌套循环,我无法摆脱。在循环内部一遍又一遍地创建准备好的语句似乎是个坏主意。

标签: javaprepared-statement

解决方案


推荐阅读