Java线程安全数据库连接

我正在编写一个servlet,通过访问和修改数据库中的某些表来处理每个请求。 我希望与数据库的连接是线程安全的。 我不想使用现有的库/框架(spring,hibernate等)。

我知道我可以通过以下方式使用java的ThreadLocal:

public class DatabaseRegistry { //assume it's a singleton private Properties prop = new Properties(); public static final ThreadLocal threadConnection = new ThreadLocal(); 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类? 或者是否有更好的方法来使所有连接线程安全?

谢谢

我不认为使数据库连接线程安全是一种常见的做法。 通常你想要的是:

  • 序列化对servlet某些部分的访问,这样一次只能有一个servlet执行代码(例如,实现SingleThreadModel接口)。
  • 锁定特定的表/表页/行,以便您可以对某个特定元组进行操作(通过更改数据库隔离级别)。
  • 使用乐观锁定来检测表中的已修改行(使用表的某些引用属性来检查当前版本是否与表中的版本相同)。

AFAIK,ThreadLocal的典型用途是为每个线程存储一个唯一的数据库连接,以便可以在业务逻辑中的不同方法中使用相同的连接,而无需每次都将其作为参数传递。 因为公共servlet容器实现使用线程来填充HTTP请求,所以保证两个不同的请求使用两个不同的数据库连接。

我知道你说过你不想使用库来做这件事,但是如果你这样做的话会更好。 选择一个标准的连接池(C3P0,DBCP或其他东西),你会比自己烘焙更快乐。 为什么你不能使用库来做到这一点?

我不确定为什么你希望你的数据库连接是线程安全的。 大多数时候建立与数据库的连接是事务的最长部分。 通常,在请求之间重用连接,并且管理开放连接池(通过框架或更典型地应用服务器)。

如果您担心对同一个表的并发修改,您可能需要查看同步方法: http : //docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html