hibernate getCurrentSession和Spring事务管理集成



 最近在Java项目中使用到了Spring和hibernate,其中使用到的事务管理,

 

spring 配置文件 如下

 

Java代码 
  1. public static void main(String[] args) {  
  2.         ApplicationContext ctx=SpringAppContext.getInstance().getApplicationContext();  
  3.         NoticeDao g=ctx.getBean(NoticeDao.class);  
  4.         /*****独立执行saveNotice()和saveNotice1()********/  
  5.         System.out.println(g.saveNotice());  
  6.         g.saveNotice1();  
  7.           
  8.         /*******在saveNotice2()中执行saveNotice()和saveNotice1()*******/  
  9.         /*g.saveNotice2();*/  
  10.     }  
  11.   
  12.     @Override  
  13.     @Transactional(propagation=Propagation.REQUIRED)  
  14.     public Session saveNotice() {  
  15.         // TODO Auto-generated method stub  
  16.         Session session= this.database.getSf().getCurrentSession();  
  17.         System.out.println("saveNotice():"+session);  
  18.         session.createSQLQuery("insert into notice(content) value('aaa');").executeUpdate();  
  19.         //session.createSQLQuery("insert into notice(content) value(bbb);").executeUpdate();  
  20.         //session.close();  
  21.         return session;  
  22.   
  23.     }  
  24.     @Override  
  25.     @Transactional(propagation=Propagation.REQUIRED)  
  26.     public void saveNotice1() {  
  27.         // TODO Auto-generated method stub  
  28.         Session session= this.database.getSf().getCurrentSession();  
  29.         System.out.println("saveNotice1():"+session);  
  30.         //session.createSQLQuery("insert into notice(content) value('aaa');").executeUpdate();  
  31.         session.createSQLQuery("insert into notice(content) value(bbb);").executeUpdate();  
  32.         //session.close();  
  33.     }  
  34.     @Override  
  35.     @Transactional(propagation=Propagation.REQUIRED)  
  36.     public void saveNotice2() {  
  37.         saveNotice();  
  38.         saveNotice1();  
  39.     }  

 1执行  saveNotice2()

 

 

结果如下

 

Java代码 
  1. saveNotice():SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2a898881 updates=org.hibernate.engine.spi.ExecutableList@16c63f5 deletions=org.hibernate.engine.spi.ExecutableList@35229f85 orphanRemovals=org.hibernate.engine.spi.ExecutableList@6d3c5255 collectionCreations=org.hibernate.engine.spi.ExecutableList@b1712f3 collectionRemovals=org.hibernate.engine.spi.ExecutableList@6986bbaf collectionUpdates=org.hibernate.engine.spi.ExecutableList@4879dfad collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4758820d unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])  
  2. Hibernate:   
  3.     insert   
  4.     into  
  5.         notice  
  6.         (content) value('aaa');  
  7. saveNotice1():SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2a898881 updates=org.hibernate.engine.spi.ExecutableList@16c63f5 deletions=org.hibernate.engine.spi.ExecutableList@35229f85 orphanRemovals=org.hibernate.engine.spi.ExecutableList@6d3c5255 collectionCreations=org.hibernate.engine.spi.ExecutableList@b1712f3 collectionRemovals=org.hibernate.engine.spi.ExecutableList@6986bbaf collectionUpdates=org.hibernate.engine.spi.ExecutableList@4879dfad collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4758820d unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])  
  8. Hibernate:   
  9.     insert   
  10.     into  
  11.         notice  
  12.         (content) value(bbb);  
  13. Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute statement  

 

 

通过分析结果 可知

saveNotice2()加入的事务处理,insert('aaa') 正常执行,insert(bbb)异常,数据库结果显示并没有插入aaa,说明事物遇到异常产生了回滚,事务处理,而通过打印对比session,可以在saveNotice2()拿到的currentsession是相同的,而事实上SaveNotice()和 saveNotice1() 都加入过session,按照getCurrentSession应该是事务执行完自动commit和关闭session,结果应该是两个session不同,且插入’aaa‘和bbb互为独立事务,但实际上回滚了数据,说明并没有已他们的事务执行或者忽略了其各自的事务,我个人猜想应该和传播行 (propagation=Propagation.REQUIRED)有关;另外getCurrentSession在同一事务下,拿到的session永远是同一个

 

2分别执行

Java代码 
  1. NoticeDao g=ctx.getBean(NoticeDao.class);  
  2.         System.out.println(g.saveNotice());  
  3.         g.saveNotice1();  

 结果如下

Java代码 
  1. saveNotice():SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2a898881 updates=org.hibernate.engine.spi.ExecutableList@16c63f5 deletions=org.hibernate.engine.spi.ExecutableList@35229f85 orphanRemovals=org.hibernate.engine.spi.ExecutableList@6d3c5255 collectionCreations=org.hibernate.engine.spi.ExecutableList@b1712f3 collectionRemovals=org.hibernate.engine.spi.ExecutableList@6986bbaf collectionUpdates=org.hibernate.engine.spi.ExecutableList@4879dfad collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4758820d unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])  
  2. Hibernate:   
  3.     insert   
  4.     into  
  5.         notice  
  6.         (content) value('aaa');  
  7. SessionImpl(<closed>)  
  8. saveNotice1():SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2cc3ad05 updates=org.hibernate.engine.spi.ExecutableList@710b18a6 deletions=org.hibernate.engine.spi.ExecutableList@119020fb orphanRemovals=org.hibernate.engine.spi.ExecutableList@3d9f6567 collectionCreations=org.hibernate.engine.spi.ExecutableList@c055c54 collectionRemovals=org.hibernate.engine.spi.ExecutableList@25e2ab5a collectionUpdates=org.hibernate.engine.spi.ExecutableList@35e5d0e5 collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@73173f63 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])  
  9. Hibernate:   
  10.     insert   
  11.     into  
  12.         notice  
  13.         (content) value(bbb);  
  14. Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute statement  

通过结果分析,getCurrentSession中的session在事务完成后会自动commit和close,getCurrentSession在相互独立事务中拿到的session是不同的,另外 getCurrentSession得到的session是和事务绑定的,要用getCurrentSession生产的session,就必须有事务环境,否则会抛出

 

 

Java代码 
  1. org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread  

 

 

一开始使用事务由于使用了 aop捕获了相关运行时异常,导致事务下异常没有被抛出,事务没能拿到运行时异常,并没有回滚数据,对于非运行时异常,事务也不会产生回滚,除非使用Springrollback-for配置,指定相关异常执行回滚

Xml代码 
  1. <!-- 切面捕获异常并写入日志 -->  
  2.     <!-- <bean id="aspectBean" class="dw.aop.log.Aspect" /> -->  
  3.     <!-- Aop配置  expression 表达式  配置dw包下所有类及子类或接口的所有方法 -->  
  4. <!--     <aop:config>  
  5.         <aop:aspect id="aspect" ref="aspectBean">  
  6.             <aop:pointcut id="logService" expression="execution(* dw..*.*(..))" />  
  7.             <aop:before pointcut-ref="logService" method="doBefore" />  
  8.             <aop:after pointcut-ref="logService" method="doAfter" />  
  9.             <aop:around pointcut-ref="logService" method="doAround" />  
  10.         </aop:aspect>  
  11.     </aop:config> -->  

 Aspect.java 

 

 

Java代码 
  1. /** 
  2.  * 环绕通知:包围一个连接点的通知,可以在方法的调用前后完成自定义的行为,也可以选择不执行 
  3.  * 类似Web中Servlet规范中的Filter的doFilter方法。 
  4.  * 
  5.  * @param pjp 
  6.  *            当前进程中的连接点 
  7.  * @return 
  8.  * @throws Throwable 
  9.  */  
  10. public Object doAround(ProceedingJoinPoint pjp){  
  11.     Object retVal = null;  
  12.         try {  
  13.             retVal = pjp.proceed();  
  14.         } catch (Throwable e) {  
  15.             e.printStackTrace();  
  16.             logger.error(pjp.getTarget().getClass().getName() + "类的方法:"  
  17.                 + pjp.getSignature().getName()+ pjp.getSignature()+"执行出错",e);  
  18.         }  
  19.     return retVal;  
  20. }  

 

以上纯属个人理解,如有错误,欢迎指正

 

 最近在Java项目中使用到了Spring和hibernate,其中使用到的事务管理,

 

spring 配置文件 如下

 

Java代码 
  1. public static void main(String[] args) {  
  2.         ApplicationContext ctx=SpringAppContext.getInstance().getApplicationContext();  
  3.         NoticeDao g=ctx.getBean(NoticeDao.class);  
  4.         /*****独立执行saveNotice()和saveNotice1()********/  
  5.         System.out.println(g.saveNotice());  
  6.         g.saveNotice1();  
  7.           
  8.         /*******在saveNotice2()中执行saveNotice()和saveNotice1()*******/  
  9.         /*g.saveNotice2();*/  
  10.     }  
  11.   
  12.     @Override  
  13.     @Transactional(propagation=Propagation.REQUIRED)  
  14.     public Session saveNotice() {  
  15.         // TODO Auto-generated method stub  
  16.         Session session= this.database.getSf().getCurrentSession();  
  17.         System.out.println("saveNotice():"+session);  
  18.         session.createSQLQuery("insert into notice(content) value('aaa');").executeUpdate();  
  19.         //session.createSQLQuery("insert into notice(content) value(bbb);").executeUpdate();  
  20.         //session.close();  
  21.         return session;  
  22.   
  23.     }  
  24.     @Override  
  25.     @Transactional(propagation=Propagation.REQUIRED)  
  26.     public void saveNotice1() {  
  27.         // TODO Auto-generated method stub  
  28.         Session session= this.database.getSf().getCurrentSession();  
  29.         System.out.println("saveNotice1():"+session);  
  30.         //session.createSQLQuery("insert into notice(content) value('aaa');").executeUpdate();  
  31.         session.createSQLQuery("insert into notice(content) value(bbb);").executeUpdate();  
  32.         //session.close();  
  33.     }  
  34.     @Override  
  35.     @Transactional(propagation=Propagation.REQUIRED)  
  36.     public void saveNotice2() {  
  37.         saveNotice();  
  38.         saveNotice1();  
  39.     }  

 1执行  saveNotice2()

 

 

结果如下

 

Java代码 
  1. saveNotice():SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2a898881 updates=org.hibernate.engine.spi.ExecutableList@16c63f5 deletions=org.hibernate.engine.spi.ExecutableList@35229f85 orphanRemovals=org.hibernate.engine.spi.ExecutableList@6d3c5255 collectionCreations=org.hibernate.engine.spi.ExecutableList@b1712f3 collectionRemovals=org.hibernate.engine.spi.ExecutableList@6986bbaf collectionUpdates=org.hibernate.engine.spi.ExecutableList@4879dfad collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4758820d unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])  
  2. Hibernate:   
  3.     insert   
  4.     into  
  5.         notice  
  6.         (content) value('aaa');  
  7. saveNotice1():SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2a898881 updates=org.hibernate.engine.spi.ExecutableList@16c63f5 deletions=org.hibernate.engine.spi.ExecutableList@35229f85 orphanRemovals=org.hibernate.engine.spi.ExecutableList@6d3c5255 collectionCreations=org.hibernate.engine.spi.ExecutableList@b1712f3 collectionRemovals=org.hibernate.engine.spi.ExecutableList@6986bbaf collectionUpdates=org.hibernate.engine.spi.ExecutableList@4879dfad collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4758820d unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])  
  8. Hibernate:   
  9.     insert   
  10.     into  
  11.         notice  
  12.         (content) value(bbb);  
  13. Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute statement  

 

 

通过分析结果 可知

saveNotice2()加入的事务处理,insert('aaa') 正常执行,insert(bbb)异常,数据库结果显示并没有插入aaa,说明事物遇到异常产生了回滚,事务处理,而通过打印对比session,可以在saveNotice2()拿到的currentsession是相同的,而事实上SaveNotice()和 saveNotice1() 都加入过session,按照getCurrentSession应该是事务执行完自动commit和关闭session,结果应该是两个session不同,且插入’aaa‘和bbb互为独立事务,但实际上回滚了数据,说明并没有已他们的事务执行或者忽略了其各自的事务,我个人猜想应该和传播行 (propagation=Propagation.REQUIRED)有关;另外getCurrentSession在同一事务下,拿到的session永远是同一个

 

2分别执行

Java代码 
  1. NoticeDao g=ctx.getBean(NoticeDao.class);  
  2.         System.out.println(g.saveNotice());  
  3.         g.saveNotice1();  

 结果如下

Java代码 
  1. saveNotice():SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2a898881 updates=org.hibernate.engine.spi.ExecutableList@16c63f5 deletions=org.hibernate.engine.spi.ExecutableList@35229f85 orphanRemovals=org.hibernate.engine.spi.ExecutableList@6d3c5255 collectionCreations=org.hibernate.engine.spi.ExecutableList@b1712f3 collectionRemovals=org.hibernate.engine.spi.ExecutableList@6986bbaf collectionUpdates=org.hibernate.engine.spi.ExecutableList@4879dfad collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4758820d unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])  
  2. Hibernate:   
  3.     insert   
  4.     into  
  5.         notice  
  6.         (content) value('aaa');  
  7. SessionImpl(<closed>)  
  8. saveNotice1():SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2cc3ad05 updates=org.hibernate.engine.spi.ExecutableList@710b18a6 deletions=org.hibernate.engine.spi.ExecutableList@119020fb orphanRemovals=org.hibernate.engine.spi.ExecutableList@3d9f6567 collectionCreations=org.hibernate.engine.spi.ExecutableList@c055c54 collectionRemovals=org.hibernate.engine.spi.ExecutableList@25e2ab5a collectionUpdates=org.hibernate.engine.spi.ExecutableList@35e5d0e5 collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@73173f63 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])  
  9. Hibernate:   
  10.     insert   
  11.     into  
  12.         notice  
  13.         (content) value(bbb);  
  14. Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute statement  

通过结果分析,getCurrentSession中的session在事务完成后会自动commit和close,getCurrentSession在相互独立事务中拿到的session是不同的,另外 getCurrentSession得到的session是和事务绑定的,要用getCurrentSession生产的session,就必须有事务环境,否则会抛出

 

 

Java代码 
  1. org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread  

 

 

一开始使用事务由于使用了 aop捕获了所有运行时异常,导致事务异常没有被抛出,事务没能拿到运行时异常,并没有回滚数据,对于非运行时异常,事务也不会产生回滚,除非使用Springrollback-for配置,指定相关异常执行回滚

Xml代码 
  1. <!-- 切面捕获异常并写入日志 -->  
  2.     <!-- <bean id="aspectBean" class="dw.aop.log.Aspect" /> -->  
  3.     <!-- Aop配置  expression 表达式  配置dw包下所有类及子类或接口的所有方法 -->  
  4. <!--     <aop:config>  
  5.         <aop:aspect id="aspect" ref="aspectBean">  
  6.             <aop:pointcut id="logService" expression="execution(* dw..*.*(..))" />  
  7.             <aop:before pointcut-ref="logService" method="doBefore" />  
  8.             <aop:after pointcut-ref="logService" method="doAfter" />  
  9.             <aop:around pointcut-ref="logService" method="doAround" />  
  10.         </aop:aspect>  
  11.     </aop:config> -->  

 Aspect.java 

 

 

Java代码 
  1. /** 
  2.  * 环绕通知:包围一个连接点的通知,可以在方法的调用前后完成自定义的行为,也可以选择不执行 
  3.  * 类似Web中Servlet规范中的Filter的doFilter方法。 
  4.  * 
  5.  * @param pjp 
  6.  *            当前进程中的连接点 
  7.  * @return 
  8.  * @throws Throwable 
  9.  */  
  10. public Object doAround(ProceedingJoinPoint pjp){  
  11.     Object retVal = null;  
  12.         try {  
  13.             retVal = pjp.proceed();  
  14.         } catch (Throwable e) {  
  15.             e.printStackTrace();  
  16.             logger.error(pjp.getTarget().getClass().getName() + "类的方法:"  
  17.                 + pjp.getSignature().getName()+ pjp.getSignature()+"执行出错",e);  
  18.         }  
  19.     return retVal;  
  20. }  

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值