Java中准备好的语句对象放在哪里?

Java中准备好的语句对象放在哪里?,java,jdbc,prepared-statement,Java,Jdbc,Prepared Statement,我想使用事先准备好的语句。我已经读到,预先准备好的语句的优点是它们不必每次都被解析/编译,这样可以减少负载。现在我的问题是,在Java中还是在我的DB系统中,“识别”已经准备好的语句发生在哪里?我这样问是因为我想知道在代码中把PreparedStatement对象存储在哪里:作为class属性,并为每个请求设置参数,或者在有请求时创建一个新的PreparedStatement对象 public class Option1 { private PreparedStatemen

我想使用事先准备好的语句。我已经读到,预先准备好的语句的优点是它们不必每次都被解析/编译,这样可以减少负载。现在我的问题是,在Java中还是在我的DB系统中,“识别”已经准备好的语句发生在哪里?我这样问是因为我想知道在代码中把PreparedStatement对象存储在哪里:作为class属性,并为每个请求设置参数,或者在有请求时创建一个新的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{
私人编制的声明或声明;
公共选择1(){
//创建myStatement对象
myStatement=conn.preparest陈述(“”);
}
公共列表查询(){
//只需使用myStatement对象
myStatement.setString(1,“foo”);
}
}
公共类选项2{
公共列表查询(){
PreparedStatement myLocalStatement=conn.prepareStatement(“”);;
//创建并使用语句
myLocalStatement.setString(1,“foo”);
}
}
现在我的问题是,更好的方法是什么,选项1还是选项2?但是,我必须在每次执行后通过执行
myStatement.close()
来进行“清理”,对吗

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


更新:如果有两个答案,一个选择1,一个选择2,我会恳请社区投票支持他们的选择^^

我会选择选项1:ie

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
       }
   }
公共类选项1{
私人编制的声明或声明;
公共选择1(){
//创建myStatement对象
myStatement.setString(1,“foo”);
}
公共列表查询(){
//只需使用myStatement对象
}
}
原因: 我可以在需要时为其指定新对象。通过做这样的事情


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

我建议使用选项2

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

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

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

但是当然,从代码的角度来看还有一些其他因素,正如其他人提到的,尤其是当您经常重用它时(如中)。重要的是,一些JDBC驱动程序正在支持它。

请记住,事先准备好的语句在开始时会变得过于繁杂,而随后的每一次使用都会使语句变得繁杂——这里有一个。

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

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,是因为它处理常见的编码错误,例如发生错误时关闭。这也保证了在执行之后,您的语句/连接/结果集将被关闭(或任何其他问题)

如果您不重用一个准备好的语句,它有什么用?@Tichodroma避免SQL注入(当然,有其他方法可以获得相同的结果)问题是如何以最有效的方式重用它。@Tichodroma这是我的观点;-)因此,我问DB系统是否识别已经准备好的语句(字符串比较或其他),或者我是否必须使用相同的对象来处理这个问题。。。当查询被发送到DB系统时,“preparedStatement()”的使用可能会给查询添加一个标志?!首先,不要盲目相信你读到的建议。量!一些数据库驱动程序在准备时做了大量的工作,以至于需要数百次调用已准备好的语句,才能在总时间内完成工作。
Option2 myQuery = new Option2();
myQyery.query("SELECT * FROM PERSON WHERE NAME = :?","ANY_NAME");
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();
 }