1.SpringBoot事务简介
SpringBoot通过@Transactional注解开启事务,在SpringBoot中默认对JPA、JDBC、MyBatis开启了事务,引入对应的依赖时,事务就默认开启。如果需要集成其它ORM框架时,比如BeatSql,需要自行配置相关的事务管理器。
SpringBoot使用TransactionAutoConfiguration类来配置事务,此配置类依赖于JtaAutoConfiguration和DataSourceTransactionManagerAutoConfiguration,而DataSourceTransactionManagerAutoConfiguration已开启了对声明式事务的支持,所以在SpringBoot中,无需显示开启使用@EanbleTransactionManagement。
SpringBoot的事务类型分为类级别和方法级别,如果在类上添加@Transactional,则说明该类所有public方法都是开启事务的。@Transactional除了可以作用在类上,还可以添加到方法上。
2.数据准备
新建一个名为mydb的数据库,在mydb中新建一个名为account的数据表,然后往数据表里插入2条数据,具体SQL语句如下。
create database if not exists mydb character set = utf8;
create table account (
id int(11) not null auto_increment,
username varchar(30),
amount int(15),
primary key (id)
);
insert into account values (1, 'mike', 2000);
insert into account values (2, 'steven', 2000);
3.引入依赖
新建一个SpringBoot工程,并在pom.xml文件中添加集成事务所需要的dependency。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
4.添加配置
在application.properties文件中添加如下配置信息。
############################################################
#
# MySQL配置
#
############################################################
### 连接信息
spring.datasource.url = jdbc:mysql://localhost:3306/mydb
### 用户名
spring.datasource.username = root
### 密码
spring.datasource.password = admin123
### 驱动
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
############################################################
#
# MyBatis配置
#
############################################################
### po类存放目录
mybatis.type-aliases-package = com.leichuangkj.transaction.dao.po
### mapper(.xml)资源文件存放路径
mybatis.mapper-locations = classpath:mybatis/mapper/*.xml
5.dao层开发
首先在项目目录“/src/main/java/com/leichuangkj/transaction”下新建“/dao/po”目录,并在po目录下新建Transfer实体类,具体代码如下。
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Transfer {
private Integer id;
private String username;
private Integer transfer;
}
然后在dao目录下新建mapper目录,并在mapper目录下新建TransferMapper接口,具体代码如下。
@Repository
public interface TransferMapper {
int updateAccount(Transfer user);
}
最后在resource目录下新建“mybatis/mapper”目录,并在mapper目录下新建TransferMapper.xml文件,具体代码如下。
<?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.leichuangkj.transaction.dao.mapper.TransferMapper" >
<update id="updateAccount" parameterType="com.leichuangkj.transaction.dao.po.Transfer">
update account
<set>
<if test="id != null">
id = #{id,jdbcType=INTEGER},
</if>
<if test="username != null">
username = #{username,jdbcType=VARCHAR},
</if>
<if test="transfer != null">
amount = amount + #{transfer,jdbcType=INTEGER},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
6.service层开发
在项目目录“/src/main/java/com/leichuangkj/transaction”下新建service目录,并在service目录下新建ITransfer接口,具体代码如下。
public interface ITransfer {
void transfer();
}
然后在service目录下新建impl目录,并在impl目录下新建TransferImpl实现类,具体代码如下。
@Service
public class TransferImpl implements ITransfer {
@Autowired
TransferMapper transferMapper;
@Transactional
@Override
public void transfer() {
Transfer id1 = new Transfer();
id1.setId(1);
id1.setUsername("mike");
id1.setTransfer(-200);
transferMapper.updateAccount(id1);
int i = 1/0;
Transfer id2 = new Transfer();
id2.setId(2);
id2.setUsername("steven");
id2.setTransfer(+200);
transferMapper.updateAccount(id2);
}
}
7.启动类开发
在启动类TransactionApplication上添加注解“@MapperScan(basePackages = “com.leichuangkj.transaction.dao.mapper”)”,然后启动项目。
@MapperScan(basePackages = "com.leichuangkj.transaction.dao.mapper")
@SpringBootApplication
public class TransactionApplication {
public static void main(String[] args) {
SpringApplication.run(TransactionApplication.class, args);
}
}
8.测试用例
在单元测试类TransactionApplicationTests中添加如下代码。
@SpringBootTest
class TransactionApplicationTests {
@Resource
TransferImpl transferImpl;
@Test
void contextLoads() {
transferImpl.transfer();
}
}
右键执行TransactionApplicationTests单元测试,这时可以看到控制台显示“1 test failed”,这是因为代码中添加了异常代码,导致转账过程失败,由于添加了事务,此时数据库里的记录不会更改。注释@Transactional,再次执行测试用例,此时,名为mike用户扣除200元的操作将会执行成功,而名为steven的用户,增加200元的操作则不会执行。
9.工程目录结构