基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之十三:用Spring嵌套事务(Nested Transaction) 回滚并返回自定义Exception
2016-10-19 10:42
579 查看
目的 :
要实现事务回滚并且能返回自定义的Exception,
首先我们先试验一下在transaction里运行:
运行之, 返回错误信息 "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()测试下), 配置事务管理时要加上嵌套事务支持:
然后给updatelist方法加上注释:@Transactional(propagation=Propagation.NESTED, rollbackFor=ModifyDataException.class), 这个注释做了两个声明,一个是"这里新开一个嵌套事务", 另一个是"抛出ModifyException时事务管理器要回滚此嵌套的事务"
于是我们将代码改为:
已成功将ModifyException回传至前端.
要实现事务回滚并且能返回自定义的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回传至前端.
相关文章推荐
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之十:Spring mvc & hibernate 事务处理(回滚)
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之五:Hibernate的事务管理、手动回滚
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之四:JdbcTemplate的事务管理
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之九:Hibernate Session Helper类,用于Entity属性与表字段的操作...
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之一 : Maven的pom.xml环境配置及注意方面
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之七:Hibernate Entity的多字段组成主键处理
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之十一:利用拦截器控制访问权限
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之十四:hibernate关于缓冲机制的巨坑!
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之三:hibernate4泛型dao的应用
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之六:Hibernate的flush和clear
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之十二: hibernate利用PostgreSQL自带的SEQUENCE生成主键
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之二: Spring/proxool数据源/Hibernate的配置
- 基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之八:一个简单例子演示Spring-MVC中多种参数传递方式
- ssh 事务不能回滚 Could not roll back Hibernate transaction; nested exception is org.hibernate.Transaction
- spring的 TransactionDefinition.PROPAGATION_NESTED 嵌套事务 应用说明
- 基于maven构建spring项目报错_NestedRuntimeException cannot be resolved
- spring 嵌套事务(Nested Transaction) 和新建事务测试
- 基于maven进行spring 和mybatis的整合(Myeclpise)
- spring事务不回滚throw的Exception异常的解决方法
- 基于Maven的Mybatis+spring+springMVC框架整合(mapper代理方式)