什么是事务
在应用程序中,事务是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元)。事务划分边界,并且在这些边界内的所有操作都受到约束,并作为单个工作单元执行。
事务管理的问题
你可以根据自己的需求来管理事务,可以自己管理事务或使用EJB容器托管事务。如果使用JDBC则可以选择JDBC的事务管理API;那么对于Hibernate,你将选择hibernate事务管理API;如果在应用中使用全局事务,你将使用JTA(Java事务API)。
如果使用全局事务,你可以用于多个事务资源(如关系数据库和消息队列),你将通过JTA管理事务。
如果使用本地事务(如与JDBC连接关联的事务),则将使用JDBC事务管理API。本地事务的问题在于它们不能跨多个事务资源工作。例如,使用JDBC连接管理事务的代码无法在全局JTA事务中运行。本地事务的另一个问题是它们是侵入性的,即你将在代码中包含所有事务代码。
在代码中使用JDBC事务的方法如下:
try{
connection.setAutoCommit(false);
...
...
connection.commit(); // for committing transaction
}catch(SQLException exp){
// transaction rollback
connection.rollback();
}
Spring事务管理
Spring Framework为事务管理提供了一个统一的抽象层来隐藏底层事务管理API,从而为不同的事务API提供一致的编程模型,例如Java Transaction API(JTA),JDBC,Hibernate和Java Persistence API(JPA)。
使用Spring事务管理,你只需编写一次代码,就可以在不同环境中的不同事务管理策略中使用它。
Spring事务也是对EJB事务的重大改进,因为可以将POJO与Spring事务一起使用。除非使用分布式事务,否则您甚至不需要Spring事务的应用程序服务器。
如何在Spring事务管理中实现抽象
Spring事务管理中的抽象是通过org.springframework.transaction.PlatformTransactionManager 接口实现的。
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
在接口中,getTransaction()方法返回一个TransactionStatus对象,该对象表示事务的状态,如果存在匹配的事务,它可能表示新事务或现有事务。getTransaction()方法中传递的参数是TransactionDefinition的一个实例。
TransactionDefinition定义Spring事务的属性,包含如下内容:
- Propagation - 定义事务的传播行为。例如,您可以指定某一行为以便代码可以继续在现有事务中运行,或者可以暂停现有事务并创建新事务。
- Isolation - 此属性定义此事务与其他事务的工作隔离的程度。例如,此事务是否可以看到来自其他事务的未提交的写入?
- Timeout - 此事务在由基础事务进行自动回滚之前运行多长时间。
- Read-only status - 当你的代码只读取但不修改数据时,可以使用只读事务。
请参阅Spring事务属性 - 传播和隔离级别设置,以了解Spring事务管理中的各种传播和隔离级别设置。
在Spring事务中定义事务管理器
Spring中的事务管理器是PlatformTransactionManager,通过它在Spring事务管理中抽象事务,但是你需要定义正确的PlatformTransactionManager实现。
PlatformTransactionManager实现通常需要了解它们工作的环境:JDBC,JTA,Hibernate等。以下是不同环境的实现类。
Spring框架中的PlatformTransactionManager实现:
- DataSourceTransactionManager - 单个JDBC DataSource的PlatformTransactionManager实现。
- HibernateTransactionManager - 用于单个Hibernate SessionFactory的PlatformTransactionManager实现。
- JmsTransactionManager - 单个JMS ConnectionFactory的PlatformTransactionManager实现。
- JpaTransactionManager - 单个JPA EntityManagerFactory的PlatformTransactionManager实现。
- JtaTransactionManager - JTA的PlatformTransactionManager实现,委托给后端JTA提供程序。
- WebLogicJtaTransactionManager - BEA WebLogic(9.0及更高版本)的特殊JtaTransactionManager变体。
- WebSphereUowTransactionManager - 委托给UOWManager实例的特定于WebSphere的PlatformTransactionManager实现。
以下是一些示例,说明如何为不同的环境定义TransactionManager。
TransactionManager for JDBC
通过引用定义的DataSource来定义。
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
TransactionManager for Hibernate
<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
TransactionManager for JPA
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<propertyname="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
TransactionManager for JTA
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
Spring事务管理类型
Spring Transaction Management支持程序式事务管理和 声明式事务管理。
程序式事务管理
Spring Framework提供了两种程序化事务管理方法:
- 使用TransactionTemplate。
- 直接使用PlatformTransactionManager实现。
如果要使用TransactionTemplate,则可以通过提供事务管理器的引用来按如下方式对其进行配置。
<propertyname="transactionTemplate">
<bean class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager" />
</bean>
</propertyname>
声明式事务管理
通过对Spring事务管理使用声明性事务,可以将事务管理与业务代码分开。您可以使用AOP使用注解或基于XML的配置来定义声明性事务。
用于声明式事务管理的注解是@Transactional。你可以在接口定义,接口上的方法,类定义或类的公共方法之前放置@Transactional。
要使Spring框架能使用@Transactional注解,你必须在XML配置中定义<tx:annotation-driven />元素。
<tx:annotation-driven transaction-manager="txManager"/>
如果使用Java配置,则可以通过将@EnableTransactionManagement添加 到配置类来启用@Transactional注解支持。
@Configuration
@EnableTransactionManagement
public class AppConfig{
...
...
}
Spring建议您只使用@Transactional注解来注解具体类(以及具体类的方法),而不是注解接口。
Spring框架中的@Transactional设置
您可以提供事务属性,如传播行为,隔离级别以及@Transactional注解。@Transactional注解的完整属性如下 :
- propagation - 可选的传播设置。
- isolation - 可选隔离级别。仅适用于传播REQUIRED或REQUIRES_NEW。
- timeout - 可选的事务超时。仅适用于传播REQUIRED或REQUIRES_NEW。使用int值以秒为单位定义。
- readOnly - 读/写与只读事务。仅适用于REQUIRED或REQUIRES_NEW。
- rollbackFor -导致回滚的可选异常类数组。
- rollbackForClassName - 导致事务回滚的异常类名字数组。
- noRollbackFor - 不会导致回滚的可选异常类数组。
- noRollbackForClassName - 不会导致事务回滚的异常类名字数组。
默认的@Transactional设置如下:
- Propagation设置为PROPAGATION_REQUIRED。
- 隔离级别为ISOLATION_DEFAULT。
- 事务是读/写。
- 事务超时默认为基础事务系统的默认超时,如果不支持超时,则默认为none。
- 任何RuntimeException都会触发回滚,而任何检查的Exception都不会。
使用@Transactional注释的示例
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public class TestService implements FooService {
public Foo getValue(String Id) {
// do something
}
// these settings have precedence for this method
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, timeout=60, rollbackFor=ValueNotFoundException.class)
public void updateValue(Person person) {
// do something
}
}
TestService类使用了@Transactional注解,该注解适用于类中所有方法将支持事务并且所有方法是只读的。方法updateValue通过拥有自己的@Transactional注解来覆盖它,该注解创建一个新事务,如果抛出ValueNotFoundException,则只读为false并且事务被回滚。