Druid工具类的封装v2.0
1.0版本的工具类,不能确保一个线程中的所有方法获取的连接都是同一个,2.0版本基于这一缺点做了改进,工具类改进代码如下
package com.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* v2.0 工具类
* 内部包含一个连接对象,并且对外提供获取连接和回收连接的方法
* 推荐写成静态,外部调用会更加方便
*
* 利用线程本地变量 存储连接信息 确保一个线程的多个方法可以获取同一个连接
* 优势:
* 事务操作的时候 service和dao是一个线程 不用在传递参数,
* 一个线程中的所有方法获取的连接都是同一个
*/
public class JdbcUtilsV2 {
private static DataSource dataSource = null;
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
static {
Properties properties = new Properties();
InputStream stream = JdbcUtilsV2.class.getResourceAsStream("/druid.properties");
try {
properties.load(stream);
} catch (IOException e) {
e.printStackTrace();
}
try {
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 对外提供连接的方法
* @return
*/
public static Connection getConnection() throws SQLException {
// 此时获取连接时 先看线程本地变量中是否存在
Connection connection = threadLocal.get();
if (connection == null){
connection = dataSource.getConnection();
threadLocal.set(connection);
}
return connection;
}
/**
* 回收连接池
* @throws SQLException
*/
public static void freeConnection() throws SQLException {
Connection connection = threadLocal.get();
if (connection != null){
threadLocal.remove(); // 把这个连接从threadLocal中清除
// 注意 connection可能在使用事务的时候 关闭自动提交了
// 这里可以在回收之前开启一下 确保连接池中的连接都是开启自动提交状态
connection.setAutoCommit(true);
connection.close();
}
}
}
这里使用了一个threadLocal变量,threadLocal以线程信息为key,以连接为value,存储线程与连接的对应关系,在使用连接之前都会先去threadLocal中取,如果没有则把该线程对应的连接保存在threadLocal中,下次同一个线程获取时,可以确保同一个线程获取的都是同一个连接!!!