Spring+Mybatis 手动控制事务

Spring+Mybatis 手动控制事务

    • 背景&问题
    • 解决方案
    • 代码
    • 参考文章

背景&问题

在【财务资金指标录入】项目中,由于对数据库的“修改”操作较为复杂,一条sql语句无法完成整个操作,所以需要在ServiceImpl中人为控制事务的提交和回滚,以保证数据库数据的准确性和一次数据库写操作的原子性。

解决方案

在ServiceImpl中注入Spring框架提供的 DataSourceTransactionManager 对象,使用该对象,并配合try…catch…代码块完成手动事务控制。

代码

ServiceImpl:

package com.sfpay.console.service.impl;

......
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
......

/**
 * 类说明:
* 财务资金指标录入模块Service层实现类 * @author 80003614 * CreateDate: 2019-2-11 */
@Service("finFundIdxService") public class FinFundIdxServiceImpl implements FinFundIdxService { private Logger logger = LoggerFactory.getLogger(this.getClass()); // 1.获取事务控制管理器 @Autowired private DataSourceTransactionManager transactionManager; @Autowired private FinFundIdxMapper finFundIdxMapper; ...... // 修改 @Override public void updateFinFundIdx(FinanceFundIndex finFundIdx) { // 2.获取事务定义 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); // 3.设置事务隔离级别,开启新事务 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 4.获得事务状态 TransactionStatus status = transactionManager.getTransaction(def); try { // 5.具体的数据库操作(多个) logger.debug("update到数据库前的JavaBean预览:" + finFundIdx.toString()); // "修改"操作需要与数据库进行3次交互,这3次写操作必须放在一个事务中控制!!! finFundIdxMapper.updateFinFundIdx(finFundIdx); // int a = 1 / 0; finFundIdxMapper.updateFinFundIdx2(finFundIdx); finFundIdxMapper.updateFinFundIdx3(finFundIdx); transactionManager.commit(status); } catch (Exception e) { transactionManager.rollback(status); throw new RuntimeException(e.getMessage()); } } }

Mapper.xml:

/**
 * 配置说明:
* 财务资金指标录入模块Mapper.xml * @author 80003614 * CreateDate: 2019-2-11 */
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.sfpay.console.dao.FinFundIdxMapper"> <resultMap id="BaseResultType" type="com.sfpay.console.domain.FinanceFundIndex"> <id column="IDX_ID" property="idxId" jdbcType="DECIMAL" /> <result column="IDX_NAME" property="idxName" jdbcType="VARCHAR" /> <result column="IDX_VAL" property="idxVal" jdbcType="DECIMAL" /> <result column="BEGIN_DATE" property="beginDate" jdbcType="DATE" /> <result column="END_DATE" property="endDate" jdbcType="DATE" /> <result column="CREATE_TIME" property="createTime" jdbcType="DATE" /> <result column="UPDATE_TIME" property="updateTime" jdbcType="DATE" /> </resultMap> ...... <!-- 更新 --> <!--"财务资金指标"的修改操作需要完成3个步骤,并用同一个事务控制 --> <!-- 第一步:针对要修改的那条记录作update或insert操作 --> <update id="updateFinFundIdx" parameterType="com.sfpay.console.domain.FinanceFundIndex" > merge into EDWSDATA.IMP_FIN_IDX idi using ( select distinct IDX_ID, IDX_NAME, #{idxVal,jdbcType=DECIMAL} IDX_VAL, #{beginDate,jdbcType=DATE} BEGIN_DATE from EDWSDATA.IMP_FIN_IDX where IDX_ID = #{idxId,jdbcType=DECIMAL} ) t on (t.IDX_ID = idi.IDX_ID and t.BEGIN_DATE = idi.BEGIN_DATE) when matched then update set idi.IDX_VAL = t.IDX_VAL, idi.END_DATE = to_date('2099-12-31','yyyy-mm-dd'), idi.UPDATE_TIME = sysdate when not matched then insert(IDX_ID, IDX_NAME, IDX_VAL, BEGIN_DATE, END_DATE, UPDATE_TIME) values(t.IDX_ID, t.IDX_NAME, t.IDX_VAL, t.BEGIN_DATE, to_date('2099-12-31','yyyy-mm-dd'), sysdate) </update> <!-- 第二步:删除这条记录后面的所有记录(以begin_date为基准) --> <delete id="updateFinFundIdx2" parameterType="com.sfpay.console.domain.FinanceFundIndex" > delete from EDWSDATA.IMP_FIN_IDX t where t.IDX_ID = #{idxId,jdbcType=DECIMAL} and t.BEGIN_DATE &gt; #{beginDate,jdbcType=DATE} </delete> <!-- 第三步:修改被修改记录的前一条记录的end_date值 --> <update id="updateFinFundIdx3" parameterType="com.sfpay.console.domain.FinanceFundIndex" > update EDWSDATA.IMP_FIN_IDX t set t.END_DATE = #{beginDate,jdbcType=DATE} where t.IDX_ID = #{idxId,jdbcType=DECIMAL} and t.BEGIN_DATE = (select BEGIN_DATE from (select BEGIN_DATE, ROW_NUMBER() OVER (PARTITION BY IDX_ID ORDER BY BEGIN_DATE DESC) as rank from EDWSDATA.IMP_FIN_IDX where IDX_ID = #{idxId,jdbcType=DECIMAL}) t1 where t1.rank = 2) </update> </mapper>

参考文章

链接: Spring+Mybatis 手动控制事务

你可能感兴趣的:(java)