Spring 事务解决方案

Posted by 暮夏有五 on 2021-01-13
Estimated Reading Time 4 Minutes
Words 818 In Total
Viewed Times

Spring 中的事务主要是利用 Aop 思想,简化事务的配置,可以通过 Java 配置也可以通过 XML 配置。

我们通过一个转账操作来看下 Spring 中的事务配置。

准备工作


创建数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE DATABASE /*!32312 IF NOT EXISTS*/`test01` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;

USE `test01`;

/*Table structure for table `account` */

DROP TABLE IF EXISTS `account`;

CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`money` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

/*Data for the table `account` */

insert into `account`(`id`,`username`,`money`) values (1,'zhangsan',1000),(2,'lisi',1000);

配置 JdbcTemplate

提供一个配置类,在配置类中配置 JdbcTemplate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Configuration
public class JdbcConfig {

@Bean
DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setUrl("jdbc:mysql:///test01");
return dataSource;
}

@Bean
JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
}

数据持久层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Repository
public class UserDao {

@Autowired
JdbcTemplate jdbcTemplate;

public void addMoney(String username, Integer money) {
jdbcTemplate.update("update account set money=money+? where username=?", money, username);
}

public void minMoney(String username, Integer money) {
jdbcTemplate.update("update account set money=money-? where username=?", money, username);
}
}

业务逻辑层

1
2
3
4
5
6
7
8
9
10
11
12
@Service
public class UserService {

@Autowired
UserDao userDao;

public void updateMoney() {
userDao.addMoney("zhangsan", 200);
int i = 1 / 0;
userDao.minMoney("lisi", 200);
}
}

相关配置

最后,在 XML 文件中,开启自动化扫描:

1
2
3
4
5
6
7
8
9
10
11
12
<context:component-scan base-package="com.antoniopeng"/>

<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="url" value="jdbc:mysql:///test01?serverTimezone=Asia/Shanghai"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
</bean>

<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>

XML 配置


XML 中配置事务一共分为三个步骤:

1. 配置 TransactionManager

1
2
3
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

2. 配置事务要处理的方法

1
2
3
4
5
6
7
8
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="update*"/>
<tx:method name="insert*"/>
<tx:method name="add*"/>
<tx:method name="delete*"/>
</tx:attributes>
</tx:advice>

注意,一旦配置了方法名称规则之后,service 中的方法一定要按照这里的名称规则来,否则事务配置不会生效

3. 配置 AOP

1
2
3
4
<aop:config>
<aop:pointcut id="pc1" expression="execution(* com.antoniopeng.hello.spring.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc1"/>
</aop:config>

4. 测试

1
2
3
4
5
6
7
8
9
10
11
@Before
public void before() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
jdbcTemplate = ctx.getBean(JdbcTemplate.class);
userService = ctx.getBean(UserService.class);
}

@Test
public void test1() {
userService.updateMoney();
}

Java 配置


如果要开启 Java 注解配置,在 XML 配置中添加如下配置:

1
<tx:annotation-driven transaction-manager="transactionManager" />

这行配置,可以代替下面两个配置:

1
2
3
4
5
6
7
8
9
10
11
12
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="update*"/>
<tx:method name="insert*"/>
<tx:method name="add*"/>
<tx:method name="delete*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pc1" expression="execution(* org.javaboy.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc1"/>
</aop:config>

然后,在需要添加事务的方法上,添加 @Transactional 注解,表示该方法开启事务,当然,这个注解也可以放在类上,表示这个类中的所有方法都开启事务。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class UserService {

@Autowired
UserDao userDao;

@Transactional
public void updateMoney() {
userDao.addMoney("zhangsan", 200);
int i = 1 / 0;
userDao.minMoney("lisi", 200);
}
}

更多干货请移步:https://antoniopeng.com


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !