hibernate getCurrentSession和Spring事务管理集成

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

spring 配置文件 如下

public static void main(String[] args) {
		ApplicationContext ctx=SpringAppContext.getInstance().getApplicationContext();
		NoticeDao g=ctx.getBean(NoticeDao.class);
		/*****独立执行saveNotice()和saveNotice1()********/
		System.out.println(g.saveNotice());
		g.saveNotice1();
		
		/*******在saveNotice2()中执行saveNotice()和saveNotice1()*******/
		/*g.saveNotice2();*/
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public Session saveNotice() {
		// TODO Auto-generated method stub
		Session session= this.database.getSf().getCurrentSession();
		System.out.println("saveNotice():"+session);
		session.createSQLQuery("insert into notice(content) value('aaa');").executeUpdate();
		//session.createSQLQuery("insert into notice(content) value(bbb);").executeUpdate();
		//session.close();
		return session;

	}
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void saveNotice1() {
		// TODO Auto-generated method stub
		Session session= this.database.getSf().getCurrentSession();
		System.out.println("saveNotice1():"+session);
		//session.createSQLQuery("insert into notice(content) value('aaa');").executeUpdate();
		session.createSQLQuery("insert into notice(content) value(bbb);").executeUpdate();
		//session.close();
	}
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void saveNotice2() {
		saveNotice();
		saveNotice1();
	}

 1执行  saveNotice2()

结果如下

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[]])
Hibernate: 
    insert 
    into
        notice
        (content) value('aaa');
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[]])
Hibernate: 
    insert 
    into
        notice
        (content) value(bbb);
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分别执行

NoticeDao g=ctx.getBean(NoticeDao.class);
		System.out.println(g.saveNotice());
		g.saveNotice1();

 结果如下

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[]])
Hibernate: 
    insert 
    into
        notice
        (content) value('aaa');
SessionImpl(<closed>)
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[]])
Hibernate: 
    insert 
    into
        notice
        (content) value(bbb);
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute statement

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

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread

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

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

 Aspect.java 

	/**
	 * 环绕通知:包围一个连接点的通知,可以在方法的调用前后完成自定义的行为,也可以选择不执行
	 * 类似Web中Servlet规范中的Filter的doFilter方法。
	 *
	 * @param pjp
	 *            当前进程中的连接点
	 * @return
	 * @throws Throwable
	 */
	public Object doAround(ProceedingJoinPoint pjp){
		Object retVal = null;
			try {
				retVal = pjp.proceed();
			} catch (Throwable e) {
				e.printStackTrace();
				logger.error(pjp.getTarget().getClass().getName() + "类的方法:"
					+ pjp.getSignature().getName()+ pjp.getSignature()+"执行出错",e);
			}
		return retVal;
	}


 

猜你喜欢

转载自yuegedetiang.iteye.com/blog/2307966
今日推荐