一、概述
编程式事务是指程序员手动的在业务代码中控制事务执行的流程,业务方法正常执行提交事务,业务方法执行过程中出现异常则回滚事务。
二、编程式事务环境搭建
2.1、项目概览
2.2、pom.xml
<dependencies><!--spring基本依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>5.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.5.RELEASE</version></dependency><!-- 数据源 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.27</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.1.0</version></dependency><!-- 普通maven项目中使用Sl4j注解 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.32</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.10</version></dependency><!-- aop --><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version></dependency><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.19</version></dependency><!-- 工具 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.3</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.11</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.22</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.1</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1.1</version></dependency></dependencies>
2.3、applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><!-- 组件扫描 --><context:component-scan base-package="org.star"/><!-- 数据源 --><context:property-placeholder location="db.properties"/><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="${db.driver}"/><property name="url" value="${db.url}"/><property name="username" value="${db.username}"/><property name="password" value="${db.password}"/></bean><!--配置sqlSessionFactory:读取配置文件,获取数据库相关的信息--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"></property><property name="typeAliasesPackage" value="org.star.entity.model"></property><property name="mapperLocations" value="classpath:mapper/*.xml"></property><property name="configuration"><bean class="org.apache.ibatis.session.Configuration"><property name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"></property></bean></property></bean><!--配置mapper接口的位置,并指定sqlSessionFactorysqlSession = sqlSessionFactory.openSession();mapper = sqlSession.getMapper();--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="org.star.mapper"></property><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property></bean><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean></beans>
2.4、db.properties
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/20230828_spring5?useSSL=false&useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai
db.username=root
db.password=123456
2.5、AccountDO.java
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/24 8:22* @Description:*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ToString(callSuper = true)
public class AccountDO implements Serializable {/*** 主键*/private Integer id;/*** 银行卡号*/private String accountNo;/*** 账户余额*/private BigDecimal amount;}
2.6、AccountMapper.java
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/24 8:23* @Description:*/
public interface AccountMapper {/*** 账户入账* @param accountNo* @param amount* @return*/Integer accountEntry(@Param("accountNo") String accountNo, @Param("amount") int amount);/*** 账户支出* @param accountNo* @param amount* @return*/Integer accountExpenditure(@Param("accountNo") String accountNo, @Param("amount") int amount);}
2.7、AccountMapper.xml
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="org.star.mapper.AccountMapper"><update id="accountEntry">update account set amount = amount + #{amount} where account_no = #{accountNo}</update><update id="accountExpenditure">update account set amount = amount - #{amount} where account_no = #{accountNo}</update></mapper>
2.8、AccountService.java
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/24 8:25* @Description:*/
public interface AccountService {/*** 转账*/void transferMoney();}
2.9、AccountServiceImpl.java
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/24 8:25* @Description:*/
@Service
public class AccountServiceImpl implements AccountService {@Resourceprivate AccountMapper accountMapper;@Resourceprivate DataSourceTransactionManager transactionManager;/*** 转账** @return*/@Overridepublic void transferMoney() {TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);try {// Jack 转出100元accountMapper.accountExpenditure("Jack", 100);// 模拟异常int i = 10 /0;// Rose 入账100元accountMapper.accountEntry("Rose", 100);// 提交事务transactionManager.commit(transactionStatus);} catch (Exception e) {e.printStackTrace();// 回滚事务transactionManager.rollback(transactionStatus);}}
}
2.10、SpringJunitTest.java
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 19:12* @Description: Spring整合单元测试*/
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringJunitTest {@Resourceprivate AccountMapper accountMapper;@Resourceprivate AccountService accountService;/*** 入账 & 出账*/@Testpublic void accountEntryTest() {Integer entryResult = accountMapper.accountEntry("Jack", 100);Integer roseResult = accountMapper.accountExpenditure("Rose", 100);log.info("entryResult:{},roseResult:{}",entryResult,roseResult);}/*** 转账*/@Testpublic void transferMoneyTest() {accountService.transferMoney();}}