我正在编写一个servlet,通过访问和修改数据库中的某些表来处理每个请求。我希望与数据库的连接是线程安全的。我不想使用现有的库/框架(spring,hibernate等)。
我知道我可以通过以下方式使用java的ThreadLocal:
public class DatabaseRegistry { //assume it's a singleton
private Properties prop = new Properties();
public static final ThreadLocal<Connection> threadConnection = new ThreadLocal<Connection>();
private Connection connect() throws SQLException {
try {
// This will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
Connection connection = DriverManager
.getConnection("jdbc:mysql://" + prop.getProperty("hostname") + "/" + prop.getProperty("database") + "?"
+ "user=" + prop.getProperty("username") + "&password=" + prop.getProperty("password"));
return connection;
} catch (SQLException e) {
throw e;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public Connection getConnection() throws SQLException {
if(threadConnection.get() == null) {
Connection connection = connect();
threadConnection.set(connection);
return threadConnection.get();
} else
return threadConnection.get();
}
private void freeConnection(Connection connection) throws SQLException {
connection.close();
threadConnection.remove();
}
}
每次调用getConnection()时,新连接都会添加到ThreadLocal对象中,然后在释放连接时将其删除。
这是正确的方法吗?或者DatabaseRegistry本身是否应该扩展ThreadLocal类?或者是否有更好的方法来使所有连接线程安全?
由于
答案 0 :(得分:2)
我认为将数据库连接设置为线程安全并不常见。通常你想要的是:
SingleThreadModel
接口)。AFAIK,ThreadLocal的典型用途是为每个线程存储唯一的数据库连接,以便可以在业务逻辑中的不同方法中使用相同的连接,而无需每次都将其作为参数传递。因为公共servlet容器实现使用一个线程来填充HTTP请求,所以保证两个不同的请求使用两个不同的数据库连接。
答案 1 :(得分:2)
我知道你说你不想使用图书馆来做这件事,但是如果你这样做的话会更好。选择一个标准的连接池(C3P0,DBCP或其他东西),你会比自己烘焙更快乐。为什么不能使用库来执行此操作?
答案 2 :(得分:0)
我不确定您为什么希望数据库连接是线程安全的。大多数时候建立与数据库的连接是事务中最长的部分。通常,连接在请求之间重用,并且管理开放连接池(通过框架或更典型的应用程序服务器)。
如果您担心对同一个表的并发修改,您可能需要查看同步方法:http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html