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 `test01` ;
USE `test01`;
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;
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
如果你喜欢这个博客或发现它对你有用,欢迎你点击右下角 “OPEN CHAT” 进行评论。也欢迎你分享这个博客,让更多的人参与进来。如果在博客中的内容侵犯了您的版权,请联系博主删除它们。谢谢你!