目录
1、事务概念与事务的四个特性ACID
2、事务操作(搭建事务操作环境)
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、事务操作(Spring事务管理介绍)
4、事务操作(注解实现-声名式事务)
4.1 事务操作(声名式事务的参数设置)
5、事务操作(XML配置文件实现-声名式事务)
6、事务操作(完全注解式实现-声名式事务)
6.1 使用完全注解方式实现事务管理的代码如下:
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);
}
}
附录0:Spring事务测试的项目结构
##数据库驱动
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
附录1:注解方式实现声名式事务代码
附录1-1:UserDao接口
@Repository
public interface UserDao {
void reduceMoney();
void addMoney();
}
附录1-2:UserDao接口的实现
@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);
}
}
附录1-3:事务类: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();
}
}
附录1-4:Spring配置文件: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>
附录1-5:声名式事务测试类
/**
* @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);
}
}
附录2:XML方式实现声名式事务代码
附录2-1:UserDao接口
@Repository
public interface UserDao {
void reduceMoney();
void addMoney();
}
附录2-2:UserDao接口的实现
@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);
}
}
附录2-3:事务类: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();
}
}
附录2-4:Spring配置文件: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>
附录2-5:声名式事务测试类
/**
* @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);
}
}