1.不指定rollbackFor
使用spring的声明式事务(即@Transactional注解)时,如果不指定rollbackFor,那么当程序发生Error时,事务将不会回滚!!!显然这将导致数据不一致!
如下述代码:
@Transactionalpublic void createXxx(final XxxCreateDTO dto) {// 其它处理......xxxRepository.insertList(this.assembleItemList(dto));}
spring官方解释如下:
2.捕获异常后,没有继续传递异常
如果事务方法捕获了异常,但是没有在catch块中继续抛出异常,那么该事务将不会回滚!!显然这将导致数据不一致!
@Transactional(rollbackFor = Exception.class)public ResultDTO apply(XxxApplyModel applyModel) {try {return internalApply(applyModel);} catch (Exception e) {// 捕获异常后的一些处理,但是却没有继续抛出异常......}}}
正确的做法有两种:
- 在catch中抛出异常
@Transactional(rollbackFor = Exception.class)public ResultDTO apply(XxxApplyModel applyModel) {try {return internalApply(applyModel);} catch (Exception e) {// 捕获异常后的一些处理,但是却没有继续抛出异常......throw e;}}
- 将事务的开启下沉到内部逻辑中,如本例中可以将事务的开启放到方法internalApply上
public ResultDTO apply(XxxApplyModel applyModel) {try {// 注意,要通过bean调用这个方法internalApply,不能通过this,// 方法内部的调用不会开启事务return internalApply(applyModel);} catch (Exception e) {// 捕获异常后的一些处理,但是却没有继续抛出异常......}}@Transactional(rollbackFor = Exception.class)public FooDTO internalApply(XxxApplyModel applyModel) {// business process......}
3.大事务问题
大事务,简单的说就是在一个事务中处理了很多其它耗时的操作,比如在事务中发起多个远程调用,耗时的校验逻辑放在了事务方法中等等,这会导致该事务的connection不能尽快释放,占用数据库资源,降低系统性能,如下面的方法:
@Transactional(rollbackFor = Exception.class)
public ResultDTO apply(ApplyDTO applyDTO) {try {// 条件校验this.validateApply(applyDTO);} catch (Exception e) {return getApplyResultOnException(e, productNo);}// 业务处理 保存数据等操作......return buildApplyResult(productNo, null, null, true);}
上述事务方法中校验逻辑validateApply是很耗时的,但是却放在了事务方法中,显然不合理。建议新加一个方法,依次调用apply方法和validateApply方法
public Foo applyXxx(ApplyDTO applyDTO) {this.validateApply(applyDTO);return apply(uniqueKey, applyDTO) }