将准备好的语句OBJECTS放在Java中的位置?

时间:2012-09-03 08:47:15

标签: java jdbc prepared-statement

我想使用预备语句。我已经读过,预处理语句的优点是它们不必每次都被解析/编译,因此减少了负载。现在我的问题是,在Java或我的数据库系统中,对已经准备好的语句的“识别”发生了什么?我问,因为我想知道在我的代码中将PreparedStatement对象存储在何处:作为class属性并为每个请求设置参数或者在有请求时创建一个新的预准备语句对象。

    public class Option1 {
       private PreparedStatement myStatement;
       public Option1() {
          // create the myStatement object
          myStatement = conn.prepareStatement("");
       }
       public List<Items> query() {
          // just use the myStatement object
          myStatement.setString(1, "foo");
       }
   }

    public class Option2 {
       public List<Items> query() {
          PreparedStatement myLocalStatement = conn.prepareStatement("");;
          // create and use the statement
          myLocalStatement.setString(1, "foo");
       }
   }

现在我的问题是,选择1还是2,更好的方法是什么?但是,我必须在每次执行后通过执行myStatement.close()权限进行“清理”吗?

也许我应该以另一种方式问它:如何以最有效的方式重复使用它?

更新:如果有两个答案,一个更喜欢选项1和一个选项2,我会请社区投票选择^^

4 个答案:

答案 0 :(得分:4)

SQL数据库正在使用完整查询(包括where子句)作为键来缓存语句的执行计划。通过使用预准备语句,无论您使用什么值(它们总是'?'),查询都是相同的。

因此,从数据库缓存的角度来看,两个选项之间没有区别。请参阅this article,其中还介绍了一些Java EE特定问题。

但当然,正如其他人所提到的,从代码的角度来看还有一些其他因素,特别是当你经常重复使用它时(比如在this example中)。重要的是,有些JDBC驱动程序支持precompilation 请记住,准备好的陈述最初是在过去,而在追赶每一次后续使用时 - 这里是great chapter about that

答案 1 :(得分:2)

我会推荐选项2

public class Option2 {
   public List<Items> query() {
      PreparedStatement myLocalStatement = conn.prepareStatement("");;
      // create and use the statement
      myLocalStatement.setString(1, "foo");
   }
}

as 如果逻辑单元分布在多个方法和数据成员中,则故障点会增加并且容易出错。

或者我愿意:

public class Option2 {
   public List<Items> query(String sql, String parameter) {
      PreparedStatement myLocalStatement = conn.prepareStatement(sql);
      // create and use the statement
      myLocalStatement.setString(1, parameter);
   }
}

并使用它:

Option2 myQuery = new Option2();
myQyery.query("SELECT * FROM PERSON WHERE NAME = :?","ANY_NAME");

答案 2 :(得分:1)

我会选择选项1:即。

public class Option1 {
       private PreparedStatement myStatement;
       public Option1() {
          // create the myStatement object
          myStatement.setString(1, "foo");
       }
       public List<Items> query() {
          // just use the myStatement object
       }
   }

原因: 我可以在需要时为它分配新的Object。通过做这样的事情

函数中的

pst = con.prepareStatement(myQuery);,在您的案例函数中将是Option1()

答案 3 :(得分:0)

就个人而言,我喜欢第二种选择,这就是我的想象

public void addAccount(String username, String password, String name) {
String query="INSERT INTO Accounts (username, password, name) VALUES (?,?,?)";
try(Connection connection = dataSource.getConnection()) {
  try(PreparedStatement statement = connection.preparedStatement(query)){
     statement.setString(1, username);
     statement.setString(2, password);
     statement.setString(3, name);
     statement.executeUpdate();
  }
 } catch(SQLException e) {
  e.printStacktrace();
 }

原因,为什么你应该使用try-with-resource只是因为它处理常见的编码错误,如发生错误时关闭。这也保证了在执行之后,您的语句/连接/结果集将被关闭(或任何其他问题)