一、事务
1、事务是数据库操作的基本单位,逻辑上一组操作,要么全成功,如果有一个失败所有的操作都失败!
经典业务场景:
银行转账 A转给B500元 A - 500 B + 500
2、事务四个特性(ACID):
a、原子性
b、一致性
c、隔离性
d、持久性
二、事务操作(搭建事务操作环境)
1、事务环境搭建
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void accountMoney(){
// tom减少100
userDao.reduceMoney();
// jack增加100
userDao.addMoney();
}
}
public interface UserDao {
// tom转钱
int reduceMoney();
// jack收钱
int addMoney();
}
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int reduceMoney(){
String sql = "update c_account set money = money - ? where username = ?";
return jdbcTemplate.update(sql,"100","tom");
}
@Override
public int addMoney() {
String sql = "update c_account set money = money + ? where username = ?";
return jdbcTemplate.update(sql,"100","jack");
}
}
@Test
public void testAffair(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
<?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"
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 " target="_blank">http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启注解扫描-->
<context:component-scan base-package="com.yinhai"/>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql:///company"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
<!-- 配置jdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入dataSource -->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
2、为什么引入事务
public void accountMoney(){
try {
// 1、开启事务
// 2、进行业务操作
// tom减少100
userDao.reduceMoney();
// jack增加100
userDao.addMoney();
// 3、没有发生异常,提交事务
} catch (Exception e) {
// 4、出现异常,事务回滚
}
}
3、事务操作-Spring事务管理介绍
a、一般会将事务添加到业务逻辑层
b、spring进行事务管理操作
编程式事务管理 和 声明式事务管理
c、声明式事务管理
基于注解方式 和 基于xml配置文件方式
d、在spring进行声明式事务管理,底层使用AOP原理
e、spring事务管理API
提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
PlatformTransactionManager
4、Spring声明式事务管理(注解方式)
a、在spring配置文件配置事务管理器
<!-- 创建事务管理器 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
b、在spring配置文件,开启事务注解
在spring配置文件中引入名称空间tx
<?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 " target="_blank">http://www.springframework.org/schema/tx/spring-tx.xsd">
开启事务注解
<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
c、在service类上面(或者类里面方法上面)添加事务注解
@Transactional,这个注解添加到类上面,也可以添加到方法上面
如果添加到类上面,类里面的所有方法都添加事务
如果添加到方法上面,只为这个方法添加事务
@Service
@Transactional
public class UserService {}
5、spring声明式事务管理参数配置 (注解方式)
a、事务传播行为 propagation
当一个事务方法被另外一个事务方法调用时候,这个事务方法如何进行
b、事务隔离级别 ioslation
1、事务有特性成为隔离性,多事务操作之间不会产生影响,不考虑隔离性产生很多问题
2、有三个读问题:脏读、不可重复读、幻读
3、脏读 :一个未提交事务读取到另一个未提交事务的数据
4、不可重复读 :一个未提交事务读取到另一提交事务修改数据
5、幻读 :一个未提交事务读取到另一提交事务添加数据
解决办法:
Serializable(串行化):一个事务在执行过程中完全看不到其他事务对数据库所做的更新。
Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他事 务对已有记录的更新。
Read Commited(读已提交数据):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事 务已经提交的对已有记录的更新
Read Uncomitted(读未提交数据):一个事务在执行过程中可以拷打其他事务没有提交的新插入的记录,而且能看到其他 事务没有提交的对已有记录的更新。
c、timeout -- 超时时间
1、事务需要在一定时间内进行提交,如果不提交进行回滚
2、默认值是-1,设置时间以秒单位进行计算
d、readOnly -- 是否只读
e、rollbackFor -- 回滚
1、设置出现哪些异常进行事务回滚
f、noRollbackFor -- 不回滚
1、设置出现哪些异常不进行事务回滚
6、spring声明式事务管理参数配置 (XML方式)
a、配置文件中配置
配置事务管理器
配置通知
配置切入点和切面
<?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 " target="_blank">http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 开启注解扫描-->
<context:component-scan base-package="com.yinhai"/>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql:///company"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
<!-- 配置jdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入dataSource -->
<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="advice">
<!-- 配置事务参数 -->
<tx:attributes>
<!-- 指定哪种规则的方法上面加事务 -->
<tx:method name="accountMoney" propagation="REQUIRED"/>
<!--<tx:method name="account*"/>-->
</tx:attributes>
</tx:advice>
<!-- 3.配置切入点和切面 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut id="pc" expression="execution(* com.yinhai.spring5.service.UserService.*(..))"/>
<!-- 配置切面 -->
<aop:advisor advice-ref="advice" pointcut-ref="pc"/>
</aop:config>
</beans>
7、spring声明式事务管理 (完全注解方式)
a、创建配置类,使用配置类替代xml配置文件
@Configuration
@ComponentScan(basePackages = "com.yinhai")
@EnableTransactionManagement
public class TxConfig {
// 数据库连接池对象
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl("jdbc:mysql:///company");
druidDataSource.setUsername("root");
druidDataSource.setPassword("123456");
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
return druidDataSource;
}
// JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
// 事务管理器对象
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
return dstm;
}
}