事务
Spring 中的事务主要是利用 Aop 思想,简化事务的配置,可以通过 Java 配置也可以通过 XML 配置。
准备工作:
我们通过一个转账操作来看下 Spring 中的事务配置。
首先准备 SQL:
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 的配置和第5小节一致。
然后,提供转账操作的方法:
@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);
}
}
@Service
public class UserService {
@Autowired
UserDao userDao;
public void updateMoney() {
userDao.addMoney("zhangsan", 200);
int i = 1 / 0;
userDao.minMoney("lisi", 200);
}
}
最后,在 XML 文件中,开启自动化扫描:
<context:component-scan base-package="org.javaboy"/>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<property name="username" value="root"/>
<property name="password" value="123"/>
<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
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2.配置事务要处理的方法
<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
<aop:config>
<aop:pointcut id="pc1" expression="execution(* org.javaboy.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc1"/>
</aop:config>
4.测试
@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配置中添加如下配置
<tx:annotation-driven transaction-manager="transactionManager" />
这行配置可以代替下面两个配置:
<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 注解,表示该方法开启事务,当然,这个注解也可以放在类上,表示这个类中的所有方法都开启事务。
@Service
public class UserService {
@Autowired
UserDao userDao;
@Transactional
public void updateMoney() {
userDao.addMoney("zhangsan", 200);
int i = 1 / 0;
userDao.minMoney("lisi", 200);
}
}