SqlSessionUtil工具类
public class SqlsessionUtil {
private static SqlSessionFactory sqlSessionFactory;
private static ThreadLocal<SqlSession> threadLocal;
//类加载时初始化sqlSessionFactory
static {
try {
InputStream inputStream= Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
threadLocal=new ThreadLocal<SqlSession>();
}
/**
* 得到sqlsession
* @return
*/
public static SqlSession getSqlCurrentSqlsession(){
SqlSession sqlSession=threadLocal.get();
if (sqlSession==null){
sqlSession=sqlSessionFactory.openSession();
threadLocal.set(sqlSession);
}
return sqlSession;
}
/**
* 回滚
* @param sqlSession
*/
public static void rollBack(SqlSession sqlSession){
if (sqlSession!=null){
sqlSession.rollback();
}
}
/**
*释放资源
* @param sqlSession
*/
public static void close(SqlSession sqlSession){
if (sqlSession!=null){
sqlSession.close();
threadLocal.remove();
}
}
}
事务处理器TransactionHandler
public class TransactionHandler implements InvocationHandler {
//目标对象
private Object target;
//构造器
public TransactionHandler(Object target) {
this.target = target;
}
//得到代理对象
public Object getProxy(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession sqlSession=null;
Object invoke=null;
try{
//手动提交事务
sqlSession = SqlsessionUtil.getSqlCurrentSqlsession();
//dowork
invoke=method.invoke(target,args);
//提交事务
sqlSession.commit();
}catch (Exception e){
//回滚
SqlsessionUtil.rollBack(sqlSession);
e.printStackTrace();
}finally {
SqlsessionUtil.close(sqlSession);
}
return invoke;
}
}
UserDao 和UserDaoImpl
public interface UserDao {
/**
* 保存用户
* @param usre
* @return
*/
int save (User usre);
}
public class UserDaoImpl implements UserDao {
@Override
public int save(User user) {
return SqlsessionUtil.getSqlCurrentSqlsession().insert("save",user);
}
}
测试类
public void TESTUTILS(){
UserDao userDao=(UserDao) new TransactionHandler( new UserDaoImpl()).getProxy();
User user =new User();
user.setSex("男");
user.setName("的发生");[code=java]
int i=userDao.save(user);
System.out.println(i);
}[/code]
调试发现 第二次从threadlocal中取出的sqlsession是null
调试 第一次进入getSqlCurrentSqlsession():
public static SqlSession getSqlCurrentSqlsession(){
SqlSession sqlSession=threadLocal.get(); //defaultsqlsession@1871
if (sqlSession==null){
sqlSession=sqlSessionFactory.openSession();
threadLocal.set(sqlSession);
}
return sqlSession;
}
第二次进入发现从threadlocal中取出来的是null,所以又重新创建了一个sqlsession 最后报错
public static SqlSession getSqlCurrentSqlsession(){
SqlSession sqlSession=threadLocal.get(); //defaultsqlsession@1875
if (sqlSession==null){
sqlSession=sqlSessionFactory.openSession();
threadLocal.set(sqlSession);
}
return sqlSession;
}
报错代码为:
org.apache.ibatis.exceptions.PersistenceException:
### Error committing transaction. Cause: org.apache.ibatis.executor.ExecutorException: Cannot commit, transaction is already closed
### Cause: org.apache.ibatis.executor.ExecutorException: Cannot commit, transaction is already closed
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:227)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:218)
at com.li.utils.TransactionHandler.invoke(TransactionHandler.java:35)
at com.sun.proxy.$Proxy6.save(Unknown Source)
at com.li.test.TESTUTILS(test.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: org.apache.ibatis.executor.ExecutorException: Cannot commit, transaction is already closed
at org.apache.ibatis.executor.BaseExecutor.commit(BaseExecutor.java:239)
at org.apache.ibatis.executor.CachingExecutor.commit(CachingExecutor.java:119)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:224)
... 28 more
打印了一下线程,发现始终都是main线程
DEBUG - PooledDataSource forcefully closed/removed all connections.
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
DEBUG - Opening JDBC Connection
DEBUG - Created connection 2109839984.
DEBUG - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@7dc19a70]
DEBUG - ==> Preparing: insert into t_user(name,sex) values(?,?)
DEBUG - ==> Parameters: 的发生(String), 男(String)
DEBUG - <== Updates: 1
Thread[main,5,main]
DEBUG - Committing JDBC Connection [com.mysql.jdbc.Connection@7dc19a70]
DEBUG - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@7dc19a70]
DEBUG - Closing JDBC Connection [com.mysql.jdbc.Connection@7dc19a70]
DEBUG - Returned connection 2109839984 to pool.
Thread[main,5,main]
Thread[main,5,main]
org.apache.ibatis.exceptions.PersistenceException:
### Error committing transaction. Cause: org.apache.ibatis.executor.ExecutorException: Cannot commit, transaction is already closed
### Cause: org.apache.ibatis.executor.ExecutorException: Cannot commit, transaction is already closed
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:227)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:218)
at com.li.utils.TransactionHandler.invoke(TransactionHandler.java:35)
at com.sun.proxy.$Proxy6.save(Unknown Source)
at com.li.test.TESTUTILS(test.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.jav