使用ThreadLocal和数据库连接绑定时,每次使用完一个连接后,在close的时候都要让当前线程与连接解绑,,否则在第二次使用这个连接的时候会空指针,因为你不能操作一个已经关闭的连接。
@Component("connectionUtil")
public class ConnectionUtil {
private ThreadLocal<Connection> connectionThreadLocal = new ThreadLocal<Connection>();
@Autowired
private DataSource dataSource;
public Connection getConnection(){
Connection conn = connectionThreadLocal.get();
try {
if (conn == null){
conn = dataSource.getConnection();
connectionThreadLocal.set(conn);
}
return conn;
} catch (Exception e){
throw new RuntimeException(e);
}
}
// 就是这里,与当前线程解绑
public void removeConnection(){
connectionThreadLocal.remove();
}
}
调用的地方:
import com.itheima.utils.util.ConnectionUtil;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.SQLException;
@Component("transManager")
@Aspect
public class TransManager {
@Autowired
ConnectionUtil connectionUtil;
@Pointcut("execution(* com.example.service.impl.AccountServiceImpl.*(..))")
public void pt(){};
@Before("pt()")
public void beginTransaction(){
try {
connectionUtil.getConnection().setAutoCommit(false);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@AfterReturning("pt()")
public void commit(){
try {
connectionUtil.getConnection().commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@AfterThrowing("pt()")
public void rollback(){
try {
connectionUtil.getConnection().rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@After("pt()")
public void release(){
try {
connectionUtil.getConnection().close();
// 在close的地方解绑
connectionUtil.removeConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}