5

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

    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

4 回答 4

5

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

因此,从数据库缓存的角度来看,您的两个选项之间没有区别。请参阅这篇文章,该文章还描述了一些 Java EE 特定问题。

但是,从代码的角度来看,当然还有其他一些因素,正如其他人所提到的,特别是当您经常重用它时(就像在这个例子中一样)。重要的是,一些 JDBC 驱动程序支持预编译
请记住,准备好的语句最初会增加开销,同时赶上后续的每次使用 - 这是一个很棒的章节

于 2012-09-03T09:01:17.307 回答
2

我会推荐选项2

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

好像逻辑单元分布在许多方法和数据成员中一样,故障点增加并且容易出错。

或者我会喜欢:

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");
于 2012-09-03T08:54:32.207 回答
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
       }
   }

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

pst = con.prepareStatement(myQuery);在函数中,在您的情况下,函数将是Option1()

于 2012-09-03T08:54:06.543 回答
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 只是因为它可以处理常见的编码错误,例如发生错误时关闭。这也保证了执行后,您的语句/连接/结果集将被关闭(或任何其他问题)

于 2017-03-16T12:21:44.407 回答