在用Java处理SQL事务的类中,我发现自己一直在使用类PreparedStatement和ResultSet。
我很想知道Java中更好(更有效)的练习;宣称他们是班上的成员......
class SqlThingy {
PreparedStatement pstx;
ResultSet rs;
public void SqlThingyMethod() {
pstx = database.connection.prepareStatement("...");
....
}
}
...或作为个别方法的局部变量?
class SqlThingy {
public void SqlThingyMethod() {
PreparedStatement pstx;
ResultSet rs;
pstx = database.connection.prepareStatement("...");
}
}
VM是否仅使用(引用)新的preparestatement覆盖类成员的内容,还是会进行一些额外的初始化,这些初始化也会声明资源,甚至每次都分配局部变量的差异?
答案 0 :(得分:2)
确保区分变量和它们指向的对象。作为一般原则,不要重用变量来指向不同的对象。这非常容易出错。
在您的具体示例中,由于您在每次调用SqlThingyMethod
时重新创建连接对象,因此将其存储在字段中可能没有任何好处。使用局部变量。
变量很便宜。物体即使不是很昂贵,也不那么便宜。在这种情况下,对象实际上可能很昂贵,但变量不是。
答案 1 :(得分:1)
实例级别字段不是线程安全的,因此JVM必须确保正确访问/使用它们(尽管 escape-analysis 可以非常好地优化它)。
方法局部变量是线程安全的,因此JVM不必担心过多关于如何使用实例。
因此,最好使用方法2(除非您从其他地方获取引用,并且引用不包含在方法中)。
答案 2 :(得分:1)
您的实例变量pstx只是一个包含引用的插槽。你并没有真正重用同一个对象,你只是抓住一个过时的引用,直到另一个方法调用出现并覆盖它。
PreparedStatement和ResultSet是从数据库连接创建的,如果获得新的数据库连接,则还必须获得新的PreparedStatement。您不能跨连接重用PreparedStatement或ResultSet。
对PreparedStatements和ResultSet使用局部变量,并在完成后关闭它们:获取连接,执行操作,并在离开方法时关闭所有jdbc资源。让这些对象挂起的时间超过绝对必要的时间并没有任何好处,它可以使数据库服务器资源不会被尽快释放。
唯一可用的优化是,如果使用相同的连接进行重复操作,则为所有这些连接保留相同的PreparedStatement实例是有意义的,这样数据库服务器就可以准备并重用该sql。
您没有说明您正在编写此代码的上下文。对于Web应用程序,您需要一个连接池,如果您为所有查询重复使用相同的连接,请参阅Is there a reason for never closing a JDBC connection?在网络应用程序中。
答案 3 :(得分:0)
简短的回答是:这取决于。
答案很长:
答案 4 :(得分:0)
你似乎认为你在重用某些东西,但你不是。每次调用该方法时,都会在两个示例中创建一个新对象。
两个主要区别:
底线:总是尽量保持范围尽可能小(例如,如果可以的话,使用局部变量)。
答案 5 :(得分:0)
将变量的范围限制为您将使用它们的最小值被认为是一种很好的做法。在这种特殊情况下,尽管您将重用变量,但请考虑变量将引用对象,例如,ResultSet将引用查询结果。如果您让变量超出范围(您将其声明为本地),则将准备由GC收集引用的值(以及它填充的内存)。如果你把它作为一个类变量,那么时间会过去,你的记忆将会被变量引用,所以在你的" SqlThingy"之前它不会被释放。类实例超出范围。
答案 6 :(得分:0)
答案是“它取决于”,但一般而言,第二种方法对性能和安全性都更好。
第一个可能导致pstx
的生命周期比第二个更长,并且还会禁用JVM优化,例如转义分析,堆栈分配等。
第一个首选的唯一原因是可以重复使用实例,从而避免初始化成本。