一, Conutils工具类:运用ThreadLocal为使每一个线程拥有同一个Connection对象。实现资源共享
public class Conutils {
/**
* Conutils类
* 功能:为每个线程创建唯一的连接对象 ->用ThreadLocal来存储
* 为什么需要Conutils?
* 因为在处理事物时,
* 只能有一个连接对象,如果有多个连接对象来处理事物
* 当产生异常时,就无法回滚到原来的状态了
* - 处理事物的步骤
* 1.得到连接 设置手动提交
* 2.通过该连接对象,进行增删改查操作。
* 3.操作成功,提交事物。操作失败,回滚事物
*
*/
private ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
private DataSource dataSource = null;
//通过set方法进行注入
//通过set方法进行注入
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 在ThreadLocal中获取连接对象,
* 如果没有,新创建一个Connection,并赋值到ThreadLocal中
* @param
* @return
* @throws SQLException
*/
public Connection getThreadConnection() throws SQLException {
Connection connection = threadLocal.get();
if (connection != null) {
return connection;
} else {
Connection ccon = dataSource.getConnection();
threadLocal.set(ccon);
return ccon;
}
}
public void relese(){
threadLocal.remove();
}
}
二,TxManager事物管理类,从Conutils获取连接对象。我们在管理事务时,只需调用TxManager的方法即可。
public class TxManager {
//事物管理类
/**
* 功能:保证一个线程的获取的连接对象只有一个
*/
private Conutils conutils = null;
//通过set进行注入
public void setConutils(Conutils conutils) {
this.conutils = conutils;
}
//设置事物提交
public void Commit() {
try {
conutils.getThreadConnection().commit();
}catch (Exception e){
throw new RuntimeException(e);
}
}
//回滚
public void RollBack() {
try {
conutils.getThreadConnection().rollback();
}catch (Exception e){
throw new RuntimeException(e);
}
}
//开始事物
public void TxStart() {
try {
conutils.getThreadConnection().setAutoCommit(false);
}catch (Exception e){
throw new RuntimeException(e);
}
}
//释放连接
/**
* 要点:
* 1.释放连接
* 2.删除该线程ThreadLocal中的值
* 原因:
* -- 当我们再通过Datasource获取处理的连接,其实是在连接池中获取的,当我们调用close方法时,
* 我们只是归还该连接到了连接池中,并没用真正的销毁连接,故当前的ThreadLocal中应该还持有这个连接的引用
* 而我们下次获取时,连接不为空,不会创建连接。而存储在ThreadLocal中的连接已经被还到连接池中了,不能使用
* 所以我们在释放资源的时候,要记得删除ThreadLocal中的值
*/
public void relese(){
try {
conutils.getThreadConnection().close();
conutils.relese();
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
主要思路:
- 1.运用Threadlocal类实现资源共享
- 2.对每个事物的处理需要用同一个connection进行操作,即拿到ThreadLocal的资源,是为了确保在当前线程下事物的连接对象只有一个。
- 3.释放资源时:connection对象只是归还到连接池中,并没有被销毁,线程使用完毕后,线程也会归还到线程池中。
- 当我们多次开启新的线程后,可能拿到原来的线程,因为Threadlocal绑定在线程上,而原来线程上的连接又没有被销毁,我们直接拿到的连接不可用(因为连接返回到连接池中了,而连接对象的引用还不为空),所以我们在释放资源时,也要释放在ThreadLocal中的资源。下次拿到的连接就是全新的连接了!