1.Spring支持编程式事务管理和声明式事务管理两种方式
2.现在主流的是声明式事务管理方式,分为基于**<tx>和<aop>**命名的声明式事务管理和基于@Transactional的方式将声明式事务管理
3.基于**<tx>和<aop>**命名空间的声明式事务,可以充分利用切点表达式的强大支持,使得管理事务更加灵活.
4.基于@Transactional的方式将声明式事务管理,简化到了极致.开发人员只需要在配置文件中加上一行配置,然后在需要实施事务管理的方法或者类上使用@Transactional指定事务规则即可实现事务管理
5.声明式事务,是建立在AOP之上的,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务.
6.声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就**不需要再业务逻辑代码中掺杂事务管理的代码,**只需要在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中.
简要回答
1.Spring支持编程式事务管理和声明式事务管理两种方式
2.声明式事务管理分为基于<tx>和<aop>命名的声明式事务管理和基于@Transactional的方式将声明式事务管理
辅助理解
1.基于@Transactional事务管理
xml配置
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
方法上添加
//添加事务注解
//1.使用 propagation 指定事务的【传播行为】, 即当前的事务方法被另外一个事务方法调用时
//如何使用事务, 【默认取值为 REQUIRED】, 即使用调用方法的事务
//REQUIRES_NEW: 事务自己的事务, 调用的事务方法的事务被挂起.
//2.使用 isolation 指定事务的【隔离级别】, 【最常用的取值为 READ_COMMITTED】
//大多数数据库的默认级别就是Read committed,比如Sql Server , Oracle。
//MySQL的默认隔离级别就是Repeatable read。
//3.默认情况下 Spring 的声明式事务对【所有的运行时异】常进行回滚. 也可以通过对应的
//属性进行设置. 通常情况下去【默认值即可】.
@Transactional(propagation=Propagation.REQUIRES_NEW,
isolation=Isolation.READ_COMMITTED,
noRollbackFor={UserAccountException.class},
rollbackFor = IOException.class,
readOnly=false,
timeout=3)
@Override
public void purchase(String username, String isbn) {}
2、基于tx和aop名字空间的xml配置式
<beans xmlns="http://www.springframework.org/schema/beans"
...
<!-- 事务管理器 -->
<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="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 切面 -->
<aop:config>
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* com.jeenotes.ssm.service.*.*(..))" />
</aop:config>
</beans>
3、springBoot中使用
@Transactional
- @Transactional 注解只能应用到 public 方法才有效
spring boot 会自动配置一个 DataSourceTransactionManager,我们只需在方法(或者类)加上 @Transactional 注解,就自动纳入 Spring 的事务管理了。
如下有一个保存用户的方法,加入 @Transactional 注解,使用默认配置,抛出异常之后,事务会自动回滚,数据不会插入到数据库
@Transactional
@Override
public void save() {
User user = new User("黑马");
userMapper.insertSelective(user);
if (true) {
throw new RuntimeException("save 抛异常了");
}
}
衍生问题
1.事务的的相关概念
a.事务特性
i.acid
2.事务的隔离级别
a.读未提交**:能读到未提交的数据。
b.读已提交**:读已提交的数据。
c.可重复读**:mysql默认,查询的都是事务开始时的数据。
d.串行读**:完全串行化读,每次都会锁表,读写互相阻塞。
3.事务并发造成的问题
a.脏读
b.不可重复读
c.幻读
d.悲观锁和乐观锁