目录
扯淡
这个东西还是遇到过不少次的
而且基本每本Spring书籍都会涉及
那么Spring事务到底重要吗?我觉得不多重要,至少和IOC、AOP比就算个弟弟。
那需要学习嘛,当然需要,
既然是复习Spring理论输出的博客,当然少不了事务
也许你无意间就看到项目代码中出现个@Transactional
上个月听我们组老哥面试校招生,每次快结束都要问你知道Spring事务传播机制吗?
我觉得在校生根本接触不到Spring事务传播,除非死记硬背,可能老哥为了考察知识面把,或者学习Spring到底认真不认真
这个事务传播机制大多直接默认就完事了
记得去年我面试的时候也问过Spring事务,也问过Spring事务怎么配,当时回答过xml配置aop的方式配置事务
ACID
- 原子性 Atomicity 一个事务中的所有操作,或者全部完成,或者全部不完成
- 一致性 Consistency 数据始终保持一致,数据不会凭空产生或消息
- 隔离性 Isolation 多个事务并发执行,不相互影响
- 持久性 Durability 事务一旦执行结束,就产生持久影响
Spring事务接口一览
PlatformTransactionManager
org.springframework.transaction.PlatformTransactionManager
Spring事务管理顶级接口
可以集成不同的数据框架,实现不同平台下的事务管理
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}
一共3个接口方法
1,getTransaction 获取 TransactionStatus
2,commit 提交事务
3,rollback回滚事务
AOP配置事务(XML)
先看一个配置事务的例子,
是我从我的github一个项目粘出来的
<?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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 公共配置项 -->
<!-- 1.1 加载properties文件 -->
<context:property-placeholder location="classpath:jdbcInfo.properties"/>
<!-- 1.2 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 2. 配置SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<property name="mappingLocations" value="classpath:pers/wmx/*/domain/*.hbm.xml"></property>
</bean>
<!-- 3.事务管理 -->
<!-- 3.1 事务管理器 -->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 3.2 事务详情
* 增删改:读写;查询:只读
-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="**" propagation="REQUIRED"/>
<tx:method name="add*" />
<tx:method name="update*"/>
<tx:method name="delete*"/>
<tx:method name="find*" />
</tx:attributes>
</tx:advice>
<!-- 3.3 aop编程 -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* pers.wmx.*.service..*.*(..))"/>
</aop:config>
<!-- 导入其他配置文件 -->
<import resource="applicationContext-user.xml"/>
<import resource="applicationContext-product.xml"/>
<import resource="applicationContext-reply.xml"/>
<import resource="applicationContext-order.xml"/>
<import resource="applicationContext-orderitem.xml"/>
</beans>
1-配置数据源
2-配置sessionfactory
3-配置事务
4-配置aop
当然我们也可以用其他的事务管理器
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
有了上面这个例子,我们一定对Spring事务有了些感觉
继续往下看
TransactionDefinition
事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)
描述了事务策略如何应用到方法上
package org.springframework.transaction;
import java.sql.Connection;
public interface TransactionDefinition {
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
int TIMEOUT_DEFAULT = -1;
//传播行为
int getPropagationBehavior();
//隔离级别
int getIsolationLevel();
//超时时间:就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务
int getTimeout();
//是否只读:只读操作 or 读写操作
boolean isReadOnly();
//事务名字
String getName();
}
事务的隔离级别和传播行为都定义到这个接口里
事务的隔离级别就不说了,见mysql事务隔离级别即可
简单的看下事务的传播行为:
事务传播指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。
如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。
/** * Support a current transaction; create a new one if none exists. * Analogous to the EJB transaction attribute of the same name. * <p>This is typically the default setting of a transaction definition, * and typically defines a transaction synchronization scope. */ int PROPAGATION_REQUIRED = 0;
上面就是Spring事务的默认传播行为,一般都直接使用默认的了,至少我目前没看到需要设置传播行为的地方
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
methodB();
// do something
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
// do something
}
单独调用methodB方法时,因为当前上下文不存在事务,所以会开启一个新的事务。
调用methodA方法时,因为当前上下文不存在事务,所以会开启一个新的事务。当执行到methodB时,methodB发现当前上下文有事务,因此就加入到当前事务中来。
TransactionStatus
事务的状态
public interface TransactionStatus extends SavepointManager, Flushable {
//是否是新创建的事务
boolean isNewTransaction();
//是否有 Savepoint
boolean hasSavepoint();
//设置为只回滚
void setRollbackOnly();
//是否为只回滚
boolean isRollbackOnly();
@Override
void flush();
//事务是否已执行完
boolean isCompleted();
}
PlatformTransactionManager.getTransaction返回一个 TransactionStatus 对象,可能代表一个新的或已经存在的事务
这就是isNewTransaction方法存在的意义:当前事务是否当前方法所创建的,只有创建事务的方法,才能且应该真正的提交事务(
commit(TransactionStatus status)
。
Spring Boot配置事务
spring boot 不需要开发者显式地配置@EnableTransactionManagement,已经自动配置了
指定事务管理器
在Spring容器中,我们手工注解@Bean 将被优先加载,框架不会重新实例化其他的 PlatformTransactionManager 实现类。
@Configuration
@MapperScan(basePackages = "xxx.mapper", markerInterface = BaseMapper.class)
@ComponentScan
public class XxxConfiguraion {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) throws SQLException {
return new DataSourceTransactionManager(dataSource);
}
}
@Transactional(rollbackFor=Exception.class)
public void methodName() {
// 不会回滚 需要补获
throw new Exception("...");
}
@Transactional(rollbackFor=Exception.class)
public void methodName1() {
// 会回滚
throw new RuntimeException("...");
}
@Transactional
一般注解在调用db接口的service方法上
指定隔离级别
@Transactional(propagation=Propagation.REQUIRES_NEW)
readOnly=true只读,不能更新,删除
@Transactional (propagation = Propagation.REQUIRED,readOnly=true)
设置超时时间
@Transactional (propagation = Propagation.REQUIRED,timeout=30)
设置数据库隔离级别
@Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)
参考
【可能是最漂亮的 Spring 事务管理详解】-
【SpringBoot事务注解详解】
https://www.jianshu.com/p/cddeca2c9245
【Spring事务(4):事务属性之7种传播行为】
https://blog.csdn.net/soonfly/article/details/70305683
转载请注明:汪明鑫的个人博客 » Spring必知必会 事务
说点什么
您将是第一位评论人!