事务可以看做是一次大的活动, 由不同的小活动组成, 这些活动要么全部成功, 要么全部失败.
SQL定义中定义了四种隔离级别:
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 是 | 是 | 是 |
读取已提交 | 否 | 是 | 是 |
可重复读 | 否 | 否 | 是 |
串行化 | 否 | 否 | 否 |
在Spring中定义了5中隔离级别:
事务传播行为指的是多个事务方法调用时, 如何定义方法间事务的传播. 在Spring中定义了7种传播行为:
一般情况下, 只有无状态的bean才可以在多线程环境下共享. Spring针对一些bean(RequestContextHolder, TransactionSynchronizationManager, LocaleContextHolder)中非线程安全的状态型对象采用ThreadLocal进行封装, 让它们也成为线程安全的状态型对象.
Spring为事务管理提供了一致的编程模板, 不管选择Spring JDBC, Hibernate, MyBatis, 都可以让用户使用同一的编程模型进行事务管理. 整个事务管理的抽象层主要包含三个接口.
事务管理器. 该类只包含三个方法: 获取事务, 回顾事务, 提交事务.
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}
定义事务的类型. 事务包含很多属性: 是否可读, 事务隔离级别, 事务传播级别.
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 = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
int TIMEOUT_DEFAULT = -1;
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
String getName();
}
代表一个事务运行的状态. 事务管理器通过状态可以知道事务的状态信息, 然后进行事务的控制事务是否完成, 是否是新的事务, 是不是只能回滚等.
public interface TransactionStatus extends SavepointManager, Flushable {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}
Spring将事务管理委托给底层具体的持久化实现框架来完成, 因此Spring为不同的持久化框架提供了PlatformTransactionManager接口的实现类, 例如JpaTransactionManager, HibernateTransactionManager, DataSourceTransactionManager, JdpTransactionManager, JtaTransactionManager. 这些事务管理器都是对特定事务实现框架的代理, 这样就可以通过Spring的高级抽象对不同种类的事务实现使用相同的方式进行管理, 而不需要关心具体的实现.
Spring将JDBC的Connection, Hibernate的Session等访问数据库的连接或会话对象统称为资源, 为了让这些资源做到多线程之间共享, Spring中的TransactionSynchronizationManager使用ThreadLocal为不同事务线程提供了独立的资源副本, 同时维护事务配置的属性和运行状态信息.
public abstract class TransactionSynchronizationManager {
// 用于保存每个事务线程对应的Connection或Session等类型的资源
private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal("Transactional resources");
// 用于保存每个事务线程对应事务的名称
private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal("Current transaction name");
// 用于保存每个事务线程对应事务的read-only状态
private static final ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal("Current transaction read-only status");
// 用于保存每个事务线程对应事务的隔离级别
private static final ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal("Current transaction isolation level");
// 用于保存每个事务线程对应事务的激活状态
private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal("Actual transaction active");
}
TransactionSynchronizationManager将Dao, Service类中影响线程安全的所有状态统一抽取到该类中, 并用ThreadLocal进行替换, 从而保证Dao, Service的线程安全性.
在实际中, 很少需要通过编程来实现事务管理. 即便如此, Spring还是为编程式事务提供模板类TransactionTemplate
以满足一些特殊场合的需要.
public class Service {
public void doSomething() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
// do something
}
});
}
}
也可以直接操作PlatformTransactionManager对事务进行commit或rollback.
XML方式配置声明式事务一共有两种, 可以使用原始的TransactionProxyFactoryBean, 也可以使用基于aop/tx命名空间的配置.
<beans>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource" />
<aop:config>
<aop:pointcut id="serviceMethod" expression="execution(* com.annwyn.service.*.*(..))" />
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
</tx:attributes>
</tx:advice>
</beans>
如果需要为不同的业务类应用不同的事务管理风格, 可以在<aop:config>
中定义另外多套事务切面进行配置.
如果rollback-for属性没有指定异常或者没有进行配置, 默认情况下只能回滚运行时异常(RuntimeException)以及错误(Error), 而捕获到编译时异常不会进行回滚.
除了XML方式配置外, 还可以使用@Transaction
进行事务管理. Transaction注解可以使用在接口定义, 接口方法, 类定义以及public方法上.
使用xml配置需要添加<tx:annotation-driven transaction-manager="txManager" />
, 而使用JavaConfig配置需要添加@EnableTransactionManagement
, 而在SpringBoot应用下, 可以不添加该注解, 因为在TransactionAutoConfiguration下已经进行了自动配置.
Spring事务大致介绍这里, 下次有时间再分析其详细代码.
原文:https://www.cnblogs.com/annwyn/p/14432914.html