ThreadLocal存储数据库Connection
在ThreadLocal中存储每个用户线程需要的数据库Connection,然后该线程的所有数据库操作都使用这个Connection,所有操作完毕,关闭这个数据库连接。
操作步骤如下:
(1)在工具类DbFactory中定义静态变量ThreadLocal。
(2)打开数据库连接(重用已有连接或创建新连接)。
(3)关闭数据库连接。
(4)事务操作封装。
public class DbFactory {
private static ThreadLocal<Connection> tlocal = new ThreadLocal<>();
public static Connection openConnection() throws ClassNotFoundException,SQLException{
Connection conn = tlocal.get();//先检查是否有已打开的数据库连接
try {
if(conn == null || conn.isClosed()) {
DbInfo db = DbInfo.instance();
Class.forName(db.getDriver());
conn = DriverManager.getConnection(db.getUrl(),db.getUname(),db.getPwd());
tlocal.set(conn); //把已打开的数据库连接存入t1
Log.logger.info(Thread.currentThread().getId() + "打开数据库");
}else {
Log.logger.info(Thread.currentThread().getId() + "使用已打开的数据库连接.");
}
} catch (ClassNotFoundException e) {
Log.logger.error(e.getMessage(),e);
throw e;
}catch( SQLException e) {
Log.logger.error(e.getMessage(),e);
throw e;
}
return conn;
}
public static void closeConnection(){
Log.logger.info(Thread.currentThread().getId() + "关闭数据库连接.");
Connection conn = tlocal.get();
tlocal.set(null);
if(conn != null) {
try {
conn.close();
} catch (Exception e) {
Log.logger.error(e.getMessage(),e);
}
}
}
}
ThreadLocal实现Connection per logic模式
模拟网上书城订单提交场景,在一次业务逻辑操作中分别要处理更新账户金额、生成订单、生成订单明细、修改图书库存等持久层操作。
在每个持久层方法的头部,都需要调用DbFactory.openConnection()获取数据库连接,在逻辑层控制事务并关闭数据库连接。
(1)在持久层的UserDao中更新账户余额、创建新订单、添加订单明细。
(2)在持久层的BookDao中更新图书数量。
(3)在逻辑层提交订单,控制事务,关闭数据库连接。
ThreadLocal实现Connection per request模式
对于Connection per request模式,可以使用ServletRequestListener监听器,在requestDestroyed()方法中关闭数据库连接。每次HTTP请求,如果调用数据库,都会在持久层打开数据库连接,然后反复重用这个数据库连接,最后在requestDestroyed()事件中关闭数据库连接。