在应用程序中,事务是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元)。事务划分边界,并且在这些边界内的所有操作都受到约束,并作为单个工作单元执行。
你可以根据自己的需求来管理事务,可以自己管理事务或使用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 Framework为事务管理提供了一个统一的抽象层来隐藏底层事务管理API,从而为不同的事务API提供一致的编程模型,例如Java Transaction API(JTA),JDBC,Hibernate和Java Persistence API(JPA)。
使用Spring事务管理,你只需编写一次代码,就可以在不同环境中的不同事务管理策略中使用它。
Spring事务也是对EJB事务的重大改进,因为可以将POJO与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事务的属性,包含如下内容:
请参阅Spring事务属性 - 传播和隔离级别设置,以了解Spring事务管理中的各种传播和隔离级别设置。
Spring中的事务管理器是PlatformTransactionManager,通过它在Spring事务管理中抽象事务,但是你需要定义正确的PlatformTransactionManager实现。
PlatformTransactionManager实现通常需要了解它们工作的环境:JDBC,JTA,Hibernate等。以下是不同环境的实现类。
Spring框架中的PlatformTransactionManager实现:
以下是一些示例,说明如何为不同的环境定义TransactionManager。
TransactionManager for JDBC
通过引用定义的DataSource来定义。
TransactionManager for Hibernate
TransactionManager for JPA
TransactionManager for JTA
Spring Transaction Management支持程序式事务管理和 声明式事务管理。
程序式事务管理
Spring Framework提供了两种程序化事务管理方法:
如果要使用TransactionTemplate,则可以通过提供事务管理器的引用来按如下方式对其进行配置。
声明式事务管理
通过对Spring事务管理使用声明性事务,可以将事务管理与业务代码分开。您可以使用AOP使用注解或基于XML的配置来定义声明性事务。
用于声明式事务管理的注解是@Transactional。你可以在接口定义,接口上的方法,类定义或类的公共方法之前放置@Transactional。
要使Spring框架能使用@Transactional注解,你必须在XML配置中定义
如果使用Java配置,则可以通过将@EnableTransactionManagement添加 到配置类来启用@Transactional注解支持。
@Configuration
@EnableTransactionManagement
public class AppConfig{
...
...
}
Spring建议您只使用@Transactional注解来注解具体类(以及具体类的方法),而不是注解接口。
您可以提供事务属性,如传播行为,隔离级别以及@Transactional注解。@Transactional注解的完整属性如下 :
默认的@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并且事务被回滚。