table of Contents
1. Transaction concept and four characteristics of transaction ACID
2. Transaction operation (build a transaction operation environment)
3. Transaction operation (Introduction to Spring transaction management)
4. Transaction operation (annotation realization-notable transaction)
4.1 Transaction operation (parameter setting of declarative transaction)
5. Transaction operation (XML configuration file implementation-declarative transaction)
6. Transaction operation (completely annotated realization-notable transaction)
6.1 The code for implementing transaction management using full annotation is as follows:
Appendix 0: Project structure of Spring transaction test
Appendix 1: Annotation to realize declarative transaction code
Appendix 1-1: UserDao interface
Appendix 1-2: Implementation of UserDao interface
Appendix 1-3: Transaction class: UserServiceTx
Appendix 1-4: Spring configuration file: bean1.xml
Appendix 1-5: Declarative Affairs Test
Appendix 2: Implementation of declarative transaction code in XML mode
Appendix 2-1: UserDao interface
Appendix 2-2: Implementation of UserDao interface
Appendix 2-3: Transaction class: UserServiceTx
Appendix 2-4: Spring configuration file: bean2.xml
Appendix 2-5: Declarative Affairs Testing
1. Transaction concept and four characteristics of transaction ACID
2. Transaction operation (build a transaction operation environment)
CREATE TABLE `RUN_Account` (
`Id` int(20) NOT NULL AUTO_INCREMENT COMMENT '用户Id',
`Name` varchar(32) NOT NULL DEFAULT '' COMMENT '姓名',
`Money` int(20) NOT NULL DEFAULT 0 COMMENT '账户余额',
PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='账户表';
insert into RUN_Account(name,money) values ("lucy",1000);
insert into RUN_Account(name,money) values ("marry",1000);
select * from RUN_Account;
3. Transaction operation (Introduction to Spring transaction management)
4. Transaction operation (annotation realization-notable transaction)
4.1 Transaction operation (parameter setting of declarative transaction)
5. Transaction operation (XML configuration file implementation-declarative transaction)
6. Transaction operation (completely annotated realization-notable transaction)
6.1 The code for implementing transaction management using full annotation is as follows:
package com.wind.spring5.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @Description: 完全注解实现声名式事务
*/
@Configuration //声名这是一个配置类
@ComponentScan(basePackages = "com.wind.*") //开启组件扫描
@EnableTransactionManagement //开启事务
public class TxConfig {
//1.创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/RUNOOB?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT");
druidDataSource.setUsername("root");
druidDataSource.setPassword("root");
return druidDataSource;
}
//2.创建JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DruidDataSource druidDataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//到IOC容器中根据类型找到druidDataSource,然后注入到JDBC对象中
jdbcTemplate.setDataSource(druidDataSource);
return jdbcTemplate;
}
//3.创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DruidDataSource druidDataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(druidDataSource);
return dataSourceTransactionManager;
}
}
package com.wind.spring5.test;
import com.wind.spring5.config.TxConfig;
import com.wind.spring5.service.UserServiceTx;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
/**
* @Description: 完全注解方式实现事务时,需要的文件详见:
* 1.被增强的类:UserServiceTx
* 2.完全注解类:TxConfig.class
* 3.测试类:UserServiceTxConfigTest
*/
@Component
public class UserServiceTxConfigTest {
@Test
public void userServiceTest() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class);
/**
* 使用完全注解形式实现的声名式事务演示
*/
UserServiceTx userServiceTx = applicationContext.getBean("userServiceTx", UserServiceTx.class);
userServiceTx.accountMoney();
System.out.println(1);
}
}
Appendix 0: Project structure of Spring transaction test
##数据库驱动
jdbc.driverClassName=com.mysql.jdbc.Driver
##MySQL连接信息
jdbc.url=jdbc:mysql://127.0.0.1:3306/RUNOOB?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT
##用户名
jdbc.username=root
##密码
jdbc.password=root
Appendix 1: Annotation to realize declarative transaction code
Appendix 1-1: UserDao interface
@Repository
public interface UserDao {
void reduceMoney();
void addMoney();
}
Appendix 1-2: Implementation of UserDao interface
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void reduceMoney() {
String sql = "update RUN_Account set money = money - ? where name = ?";
Object[] args = {100, "lucy"};
jdbcTemplate.update(sql, args);
}
@Override
public void addMoney() {
String sql = "update RUN_Account set money = money + ? where name = ?";
Object[] args = {100, "marry"};
jdbcTemplate.update(sql, args);
}
}
Appendix 1-3: Transaction class: UserServiceTx
/**
* @Description: 推荐使用的是声名式事务:这是注解的方式实现的,详见Spring配置文件:bean1.xml
* 事务管理的参数:
* 1.propagation:事务传播行为
* 2.isolation:事务隔离级别
* 3.timeout:事务超时时间
* 4.readonly:事务是否只能做读操作而不能做非读操作
* 5.rollbackFor:遇到了哪些异常,进行事务回滚
* 6.noRollbackFor:遇到了哪些异常,不进行事务回滚
*/
@Service
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, timeout = -1, readOnly = false)
public class UserServiceTx {
@Autowired
private UserDao userDao;
public void accountMoney() {
//lucy少钱
userDao.reduceMoney();
//模拟程序异常
double i = 10 / 0;
//marry多钱
userDao.addMoney();
}
}
Appendix 1-4: Spring configuration file: bean1.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
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">
<!--开启SpringBean的组件扫描-->
<context:component-scan base-package="com.wind.spring5"/>
<!--在Spring配置文件开启自动生成代理对象-->
<aop:aspectj-autoproxy/>
<!--获取Spring需要读取的数据库配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源:使用德鲁伊数据库连接池这个工具配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- 获取properties文件内容,根据key获取,使用spring表达式获取 -->
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--创建JdbcTemplate对象,同时使用set方法注入dataSource属性-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--1.在Spring配置文件中,使用声名式事务时需要创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--2.在Spring配置文件中,开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
Appendix 1-5: Declarative Affairs Test
/**
* @Description: 注解方式实现事务时,需要的文件详见:
* 1.被增强的类:UserServiceTx
* 2.注解形式配置的Spring配置文件:bean1.xml
* 3.测试类:UserServiceTxTest
*/
@Component
public class UserServiceTxTest {
@Test
public void userServiceTest() {
String spring = "bean1.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(spring);
/**
* 未使用事务时的演示
*/
//UserServiceNoTx userServiceNoTx = applicationContext.getBean("userService", UserServiceNoTx.class);
//userServiceNoTx.accountMoney();
//System.out.println(1);
/**
* 使用声名式事务时的演示
*/
UserServiceTx userServiceTx = applicationContext.getBean("userServiceTx", UserServiceTx.class);
userServiceTx.accountMoney();
System.out.println(1);
}
}
Appendix 2: Implementation of declarative transaction code in XML mode
Appendix 2-1: UserDao interface
@Repository
public interface UserDao {
void reduceMoney();
void addMoney();
}
Appendix 2-2: Implementation of UserDao interface
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void reduceMoney() {
String sql = "update RUN_Account set money = money - ? where name = ?";
Object[] args = {100, "lucy"};
jdbcTemplate.update(sql, args);
}
@Override
public void addMoney() {
String sql = "update RUN_Account set money = money + ? where name = ?";
Object[] args = {100, "marry"};
jdbcTemplate.update(sql, args);
}
}
Appendix 2-3: Transaction class: UserServiceTx
/**
* @Description: 推荐使用的是声名式事务:这是XML的方式实现的,详见Spring配置文件:bean2.xml
* 事务管理的参数:
* 1.propagation:事务传播行为
* 2.isolation:事务隔离级别
* 3.timeout:事务超时时间
* 4.readonly:事务是否只能做读操作而不能做非读操作
* 5.rollbackFor:遇到了哪些异常,进行事务回滚
* 6.noRollbackFor:遇到了哪些异常,不进行事务回滚
*/
@Service
public class UserServiceTxXML {
@Autowired
private UserDao userDao;
public void accountMoney() {
//lucy少钱
userDao.reduceMoney();
//模拟程序异常
double i = 10 / 0;
//marry多钱
userDao.addMoney();
}
}
Appendix 2-4: Spring configuration file: bean2.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
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">
<!--开启SpringBean的组件扫描-->
<context:component-scan base-package="com.wind.spring5"/>
<!--在Spring配置文件开启自动生成代理对象-->
<aop:aspectj-autoproxy/>
<!--获取Spring需要读取的数据库配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源:使用德鲁伊数据库连接池这个工具配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- 获取properties文件内容,根据key获取,使用spring表达式获取 -->
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--创建JdbcTemplate对象,同时使用set方法注入dataSource属性-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--1.配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--配置事务的数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--2.配置通知:增强的逻辑-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="accountMoney" propagation="REQUIRED"/>
<!--account开头的方法都会被增强-->
<!--<tx:method name="account*" propagation="REQUIRED"/>-->
</tx:attributes>
</tx:advice>
<!--3.配置切入点和切面-->
<aop:config>
<!--配置切入点:被增强的方法-->
<aop:pointcut id="pc" expression="execution(* com.wind.spring5.service.UserServiceTxXML.*(..))"/>
<!--配置切面:把通知织入到切入点的过程-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
</aop:config>
</beans>
Appendix 2-5: Declarative Affairs Testing
/**
* @Description: XML方式实现事务时,需要的文件详见:
* 1.被增强的类:UserServiceTxXML
* 2.XML形式配置的Spring配置文件:bean2.xml
* 3.测试类:UserServiceTxXMLTest
*/
@Component
public class UserServiceTxXMLTest {
@Test
public void userServiceTest() {
String spring = "bean2.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(spring);
/**
* 使用声名式事务时的演示
*/
UserServiceTxXML userServiceTxXML = applicationContext.getBean("userServiceTxXML", UserServiceTxXML.class);
userServiceTxXML.accountMoney();
System.out.println(1);
}
}