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
uj5u.com熱心網友回復:
刪了SqlsessionUtil.close(sqlSession);uj5u.com熱心網友回復:
感覺不對,為啥會拿到已經關閉的sqlsession物件才是問題所在,這個有點怪異uj5u.com熱心網友回復:
專案打個包丟百度網盤分享下,有點意思,不過看日志,connection已經被關閉了
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.
mybatis獲取connection,通過Transaction介面,最終落到datasource獲取connection,如果connection的autoCommit屬性是True,那估計手動提交就翻車了
uj5u.com熱心網友回復:
我重新建了個專案發現沒問題uj5u.com熱心網友回復:
鏈接:https://pan.baidu.com/s/1-dE6RojPOS3lWzrbfyjx2Q提取碼:79wx
復制這段內容后打開百度網盤手機App,操作更方便哦
uj5u.com熱心網友回復:
還是不行 懵逼了uj5u.com熱心網友回復:
拿你代碼跑了下 沒問題
uj5u.com熱心網友回復:
我一直都會得到兩個 sqlsession 報錯 太浪費時間了不研究了uj5u.com熱心網友回復:
我之前重新創了一個專案 發現沒問題 之后就配置了一下tomcat 不是maven上的插件(debug不習慣) 就又不行了轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/250369.html
標籤:Java SE
