基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之十三:用Spring嵌套事务(Nested Transaction) 回滚并返回自定义Exception

      目的 :

要实现事务回滚并且能返回自定义的Exception,

      首先我们先试验一下在transaction里运行:

@Transactional
public class xxx {
/****
	 * 修改/删除/增加 Controller接口
	 * @param pvReq
	 * @param pvLogin
	 * @param pvLocale
	 * @return
	 * @throws Exception
	 */
	public JSONData updateList(CommonReqUpdBean pvReq,String pvLogin, Locale pvLocale) throws Exception {		
		JSONData lvRet=new JSONData();
		try {
			for (CommonReqUpdBean.DataBean bean : pvReq.data) {
				switch (bean.action) {
				case CommonReqUpdBean.ACTION_DELETE: {
					mTjDistributionDao.removeById((String)bean.key.id.get("fj_distribute_list"));
					break;
				}
				case CommonReqUpdBean.ACTION_EDIT: {
					TjDistributionList lvRec=getDistributionList((String) bean.key.id.get("fj_distribute_list"), pvLocale,null);					
					CommonReqUpdBean.copySomeValuesToEntity(bean.data,lvRec, "fj_distribute_user","fj_part_rel_user");
					update(lvRec, false, pvLogin,pvLocale);					
					break;
				}
				case CommonReqUpdBean.ACTION_INSERT: {									
					TjDistributionList lvRec=CommonReqUpdBean.getBean(bean.data, TjDistributionList.class);
					TjDistributionList lvE = mTjDistributionDao.get(lvRec.getFjDistributeList());
					if (lvE != null) {
						lvRet.errCode = 1;
						lvRet.errMsg = MessageSourceHelper.getMessage("common.exists_failed", null);
						break;
					}
					update(lvRec, true, pvLogin,pvLocale);									
					break;
				}
				}
			}
		} catch (ModifyDataException e) {
			mTjDistributionDao.clear();
			mTjDistributionDao.getSession().getTransaction().rollback();
			jsonDataFillErrMsg(lvRet, e);
			throw e;
		}
		finally{
		}
		return lvRet;
	}
	
	...
}

     运行之, 返回错误信息 "Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started", 这是由于updateList运行完毕后, 事务管理器会自动commit,但由于我在Catch exception时已经rollback,但是就触发起这个"意料之外"的Exception, 因为这样,也就不能正常回传 JSONDATA数据.

    解决这个问题当然可以用上一节我们讲的新开一个session和transaction来操作, 但如果用当前session和transaction又如何解决呢? 这里要用到嵌套事务.

    要嵌套事务能正常工作必须满足以下条件: 你的数据库支持检查点(用Connection.getMetaData().supportsSavepoints()测试下), 配置事务管理时要加上嵌套事务支持:

<!-- 定义事务管理 -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
        <property name="nestedTransactionAllowed">
        	<value>true</value>
        </property>
    </bean>

       然后给updatelist方法加上注释:@Transactional(propagation=Propagation.NESTED, rollbackFor=ModifyDataException.class), 这个注释做了两个声明,一个是"这里新开一个嵌套事务", 另一个是"抛出ModifyException时事务管理器要回滚此嵌套的事务"   

     于是我们将代码改为:

/****
	 * 修改/删除/增加 Controller接口
	 * @param pvReq
	 * @param pvLogin
	 * @param pvLocale
	 * @return
	 * @throws Exception
	 */
	@Transactional(propagation=Propagation.NESTED, rollbackFor=ModifyDataException.class)
	public JSONData updateList(CommonReqUpdBean pvReq,String pvLogin, Locale pvLocale) throws Exception {		
		JSONData lvRet=new JSONData();
		
		//mTjDistributionDao.getSession().getTransaction().begin();
		try {
			for (CommonReqUpdBean.DataBean bean : pvReq.data) {
				switch (bean.action) {
				case CommonReqUpdBean.ACTION_DELETE: {
					mTjDistributionDao.removeById((String)bean.key.id.get("fj_distribute_list"));
					break;
				}
				case CommonReqUpdBean.ACTION_EDIT: {
					TjDistributionList lvRec=getDistributionList((String) bean.key.id.get("fj_distribute_list"), pvLocale,null);					
					CommonReqUpdBean.copySomeValuesToEntity(bean.data,lvRec, "fj_distribute_user","fj_part_rel_user");
					update(lvRec, false, pvLogin,pvLocale);					
					break;
				}
				case CommonReqUpdBean.ACTION_INSERT: {									
					TjDistributionList lvRec=CommonReqUpdBean.getBean(bean.data, TjDistributionList.class);
					TjDistributionList lvE = mTjDistributionDao.get(lvRec.getFjDistributeList());
					if (lvE != null) {
						lvRet.errCode = 1;
						lvRet.errMsg = MessageSourceHelper.getMessage("common.exists_failed", null);
						break;
					}
					update(lvRec, true, pvLogin,pvLocale);									
					break;
				}
				}
			}
			//mTjDistributionDao.getSession().getTransaction().commit();
		} catch (ModifyDataException e) {
			mTjDistributionDao.clear();
			//mTjDistributionDao.getSession().getTransaction().rollback(); 不用自己回滚,交给事务管理器做
			jsonDataFillErrMsg(lvRet, e);
			throw e;
		}
		finally{
		}
		return lvRet;
	}	


已成功将ModifyException回传至前端.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值