Spring的事务控制
编程式事务控制相关对象
PlatformTransactionManager
就是一个接口
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kn2aorFd-1650979333138)(spring.assets/image-20220426160508206.png)]](https://img-blog.csdnimg.cn/3c415af63dff4f68976e3612b059f2fb.png)
TransactionDefinition
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K7ORNYeJ-1650979333140)(spring.assets/image-20220426160827936.png)]](https://img-blog.csdnimg.cn/40f7bcf2e2f44a639cd2c180b5cd3ecd.png)
事务隔离级别
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eV2DO8nh-1650979333140)(spring.assets/image-20220426163804750.png)]](https://img-blog.csdnimg.cn/8440ba8dea6247e0960011cf7da27eab.png)
事务传播行为
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TzxEKjSu-1650979333141)(spring.assets/image-20220426164042649.png)]](https://img-blog.csdnimg.cn/00e1aed63b0d4b8c80a42caa4d9db27b.png)
TransactionStatus
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-chc4EL9r-1650979333142)(spring.assets/image-20220426164712770.png)]](https://img-blog.csdnimg.cn/60a286e122d046a38b8b18c1a5e34688.png)
基于XML的声明式事务控制
什么是声明式事务控制
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cQCylPJd-1650979333142)(spring.assets/image-20220426165401112.png)]](https://img-blog.csdnimg.cn/6e9095e8b1224f39a20e3ff0aecc21b8.png)
转账业务环境搭建
新建项目、导入相关依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
编写Dao层
package com.taotao.dao;
import org.springframework.jdbc.core.JdbcTemplate;
@SuppressWarnings({"all"})
public interface AccountDao {
void setJdbcTemplate(JdbcTemplate jdbcTemplate);
void out(String outMan,double money);
void in(String inMan,double money);
}
package com.taotao.dao.impl;
import com.taotao.dao.AccountDao;
import org.springframework.jdbc.core.JdbcTemplate;
@SuppressWarnings({"all"})
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void out(String outMan, double money) {
jdbcTemplate.update("update account set money = money-? where name=?",money,outMan);
}
public void in(String inMan, double money) {
jdbcTemplate.update("update account set money=money+? where name=?",money,inMan);
}
}
实体类
package com.taotao.domain;
@SuppressWarnings({"all"})
public class Account {
private String name;
private double money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"name='" + name + '\'' +
", money=" + money +
'}';
}
}
service层
package com.taotao.service;
import com.taotao.dao.AccountDao;
@SuppressWarnings({"all"})
public interface AccountService {
void setAccountDao(AccountDao accountDao);
void transfer(String outMan,String inMan,double money);
}
package com.taotao.service.impl;
import com.taotao.dao.AccountDao;
import com.taotao.service.AccountService;
@SuppressWarnings({"all"})
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(String outMan, String inMan, double money) {
accountDao.out(outMan,money);
accountDao.in(inMan,money);
}
}
操作类
package com.taotao.controller;
import com.taotao.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@SuppressWarnings({"all"})
public class AccountController {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService = app.getBean(AccountService.class);
accountService.transfer("ano","lucy",500);
}
}
Spring.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 http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="com.taotao.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="accountService" class="com.taotao.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
</beans>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/Test
jdbc.username=root
jdbc.password=12345
测试转账成功
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SOnLAyJd-1650979333143)(spring.assets/image-20220426182923333.png)]](https://img-blog.csdnimg.cn/1d2c1899f9f84a99b78fb4c13c739cbb.png)
声明式事务控制的表现
当数据异常时,终止提交事务
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dCqRUAn9-1650979333144)(spring.assets/image-20220426182322592.png)]](https://img-blog.csdnimg.cn/89ffb627d6d9438c8923db908cb4dd67.png)
编辑spring.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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="com.taotao.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="accountService" class="com.taotao.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.taotao.service.impl.*.*(..))"></aop:advisor>
</aop:config>
</beans>
在业务成加个异常切入点
当异常时,不提交数据
package com.taotao.service.impl;
import com.taotao.dao.AccountDao;
import com.taotao.service.AccountService;
@SuppressWarnings({"all"})
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(String outMan, String inMan, double money) {
accountDao.out(outMan,money);
int i = 1 / 0;
accountDao.in(inMan,money);
}
}
成功测试
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-47eT0LMc-1650979333144)(spring.assets/image-20220426194311024.png)]](https://img-blog.csdnimg.cn/58eb0947d3cd4f76b428b2eb21a89f88.png)
运行
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TbPtjcj4-1650979333145)(spring.assets/image-20220426194424275.png)]](https://img-blog.csdnimg.cn/c319074761cf464c9735140e6a38d6f8.png)
不会滚事务的情况
注销语句
测试运行
钱少了500
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KOuxghBJ-1650979333145)(spring.assets/image-20220426194650096.png)]](https://img-blog.csdnimg.cn/884810aedf444d40a97c36cfcda6a2cb.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6cfr7X43-1650979333146)(spring.assets/image-20220426194638473.png)]](https://img-blog.csdnimg.cn/1ce17a8625484a92a5b9699b198c6cda.png)
切点方法的事务参数的配置
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kw1mbSLE-1650979333146)(spring.assets/image-20220426203918903.png)]](https://img-blog.csdnimg.cn/c55e9e117c494fd08e46e070727fa908.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HXZuxM1h-1650979333147)(spring.assets/image-20220426204127352.png)]](https://img-blog.csdnimg.cn/0a1c94480d584139bd51045f35e131ff.png)
基于注解的声明式事务控制
复制项目
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UpgFDvaP-1650979333147)(spring.assets/image-20220426205907333.png)]](https://img-blog.csdnimg.cn/04e8fe570292425b8eb6565787b1d3da.png)
注解修改dao层
package com.taotao.dao.impl;
import com.taotao.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@SuppressWarnings({"all"})
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void out(String outMan, double money) {
jdbcTemplate.update("update account set money = money-? where name=?",money,outMan);
}
public void in(String inMan, double money) {
jdbcTemplate.update("update account set money=money+? where name=?",money,inMan);
}
}
注解修改service层
package com.taotao.service.impl;
import com.taotao.dao.AccountDao;
import com.taotao.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@SuppressWarnings({"all"})
@Service("accountService")
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
@Autowired
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(String outMan, String inMan, double money) {
accountDao.out(outMan,money);
int i = 1 / 0;
accountDao.in(inMan,money);
}
}
Spring.xml组件扫描
注意context命名空间配置
<context:component-scan base-package="com.taotao"/>
我们删除一些配置,使用注解完成
下面的都删除
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.taotao.service.impl.*.*(..))"></aop:advisor>
</aop:config>
我们service层加注解(方式1)
package com.taotao.service.impl;
import com.taotao.dao.AccountDao;
import com.taotao.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@SuppressWarnings({"all"})
@Service("accountService")
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
@Autowired
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
public void transfer(String outMan, String inMan, double money) {
accountDao.out(outMan,money);
accountDao.in(inMan,money);
}
@Transactional(isolation = Isolation.DEFAULT)
public void xxx(){
}
}
我们service层加注解(方式2)
package com.taotao.service.impl;
import com.taotao.dao.AccountDao;
import com.taotao.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@SuppressWarnings({"all"})
@Service("accountService")
@Transactional(isolation = Isolation.REPEATABLE_READ)
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
@Autowired
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(String outMan, String inMan, double money) {
accountDao.out(outMan,money);
accountDao.in(inMan,money);
}
public void xxx(){
}
}
我们service层加注解(方式3)
就近原则
package com.taotao.service.impl;
import com.taotao.dao.AccountDao;
import com.taotao.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@SuppressWarnings({"all"})
@Service("accountService")
@Transactional(isolation = Isolation.REPEATABLE_READ)
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
@Autowired
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED)
public void transfer(String outMan, String inMan, double money) {
accountDao.out(outMan,money);
accountDao.in(inMan,money);
}
public void xxx(){
}
}
Spring配置注解驱动
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<context:component-scan base-package="com.taotao"/>
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="com.taotao.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="accountService" class="com.taotao.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
成功测试
转账成功
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PgeYjJlo-1650979333148)(spring.assets/image-20220426211808295.png)]](https://img-blog.csdnimg.cn/33f8e735ff3e40f6bd01926aa0747a6a.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PdRfVYt4-1650979333148)(spring.assets/image-20220426211911870.png)]](https://img-blog.csdnimg.cn/d6b49d108e7e4a5890cd27f8ec4016b0.png)
转账失败
事务中断,不提交
accountDao.out(outMan,money);
int i = 1 / 0;
accountDao.in(inMan,money);
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yE0xH4hX-1650979333148)(spring.assets/image-20220426212046025.png)]](https://img-blog.csdnimg.cn/5270cc1849034340b3812be017dd67e4.png)
|