Java 静态类/方法中使用方法级连接的池数据库访问是否安全?
我在这里读了很长时间,现在我遇到了一个问题,我真的想不起来了 为了便于访问和节省对象创建开销,我有一个实现数据库访问的静态类。使用的JVM实现是Tomcat,连接池使用org.apache.commons.dbcp 我在这里和其他地方读了很多关于线程安全、堆和堆栈的书,但是如果我的静态类上的多个方法调用不会相互干扰,我就不能得出一个明确的结论。我读过的大多数主题都涉及实例方法,而我使用的是静态方法,这可能有我忽略的含义 如果我理解正确,因为变量connection、statement、resultset都在方法级别,那么每个函数调用在堆栈上都应该有一个对堆中唯一对象的唯一引用,并且多个方法调用不可能相互干扰 我是对的,还是应该被纠正?任何帮助都将不胜感激 (简称)代码为:Java 静态类/方法中使用方法级连接的池数据库访问是否安全?,java,connection-pooling,static-methods,Java,Connection Pooling,Static Methods,我在这里读了很长时间,现在我遇到了一个问题,我真的想不起来了 为了便于访问和节省对象创建开销,我有一个实现数据库访问的静态类。使用的JVM实现是Tomcat,连接池使用org.apache.commons.dbcp 我在这里和其他地方读了很多关于线程安全、堆和堆栈的书,但是如果我的静态类上的多个方法调用不会相互干扰,我就不能得出一个明确的结论。我读过的大多数主题都涉及实例方法,而我使用的是静态方法,这可能有我忽略的含义 如果我理解正确,因为变量connection、statement、resul
public class DBQuery{
private static String pathToDataSource = "";
private static javax.naming.Context cxt = null;
private static javax.sql.DataSource ds = null;
private static void getDataSource() throws Exception {
if(pathToDataSource.equals("")){ pathToDataSource = Config.getParam("PathToDataSource"); }
cxt = new javax.naming.InitialContext();
ds = (javax.sql.DataSource) cxt.lookup(pathToDataSource);
}
private static Connection connect() throws Exception {
if(ds==null){ getDataSource(); }
return ds.getConnection();
}
public static Vector doDBquery(String querystring) throws Exception {
Vector retVec = new Vector();
Connection connection = null;
Statement statement = null;
ResultSet resultset = null;
try {
connection = getConnection();
statement = connection.createStatement();
resultset = statement.executeQuery(querystring);
...
} catch(Exception e) {
...
} finally {
myFinallyBlock(resultset, statement, connection);
}
return retVec;
}
// more methods like doDBInsert() following, hence closure in separate myFinallyBlock
private static void myFinallyBlock(ResultSet resultset, Statement statement, Connection connection) {
try {
if (resultset != null) resultset.close();
} catch (SQLException e) { resultset = null; }
try {
if (statement != null) statement.close();
} catch (SQLException e) { statement = null; }
try {
if (connection != null) connection.close();
} catch (SQLException e) { connection = null; }
}
} //close class
是的,您就在方法内部,在您在方法内部使用共享变量之前,没有并发问题,换句话说,“无状态对象总是线程安全的。” Servlet就是一个很好的例子;) 已编辑。 为了确保代码安全,我建议您执行以下操作:
private static Connection connect() throws Exception {
if (ds == null) {
synchronized (Connection.class) {
if (ds == null) {
getDataSource();
}
}
}
return ds.getConnection();
}
这是个好消息,但是静态类算不算无状态对象?在我看来,这几乎是一样的,但实际上没有实例化对象。这正是我的问题,因为其他主题总是关于可实例化的类。感谢您的建议,如果我没有读错,那么数据源初始化只能由一个线程执行,而其他线程不能并发访问,同时使用Connection.class作为监视器,允许其他线程同时调用其他方法,正确吗?不,它将在连接初始化期间锁定整个类,但是如果没有连接,您的类就没有多大用处,而且时间也不会太长,初始化之后,它将在不影响性能的情况下工作。但是,如果您为初始化的性能而烦恼,您可以将您的连接设置为静态最终连接,并在静态初始化块中进行设置。仅仅想到你的代码就教会了我很多;您将null检查加倍,因为在此期间它可能已经被初始化,并且您没有将getDataSource()作为一个整体进行同步,因为最初它可能会在某些时候重新初始化。我首先有一个静态全局连接,导致“连接已关闭”错误,当然,因为所有调用都在同一个连接对象上工作。因此,我们采用了方法级方法。因此,我试图理解您的方法,并认为将监视器附加到DBquery.class以外的其他内容不会锁定整个类。那么,为什么要将其附加到Connection.class?当然,你是对的,它在没有数据源的情况下没有用处。非常感谢您的帮助和见解:-)