1.用四个词来表示事务
ACID
2.理解Spring对事务管理的支持
Spring提供了对编码式和声明式事务管理的支持。Spring的事务管理能力超过了EJB.
Spring通过回调机制将实际的事务从事务性的代码中抽象出来。如果应用程序只使用一种持久化资源,Spring可以使用持久化机制本身所提供的
事务性支持。如果应用程序的事务跨多个资源,那么Spring会使用第三方的JTA实现来支持分布式(XA)事务。
编码式事务允许用户在代码中精确定义事务的边界,而声明式事务(基于AOP)有助于用户将操作与事务规则进行解耦。
Spring对声明式事务的支持会让人联想起EJB的容器管理事务(CMT)。他们都允许你声明式地定义事务边界。但是Spring的声明式事务要胜过CMT.
因为它允许你声明额外的一些属性,例如隔离级别和超时。
3.选择事务管理器
Spring不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给JTA或者其他持久化机制所提供的平台相关的事务实现。
每个事务管理器都会充当某一特定平台的事务实现的门面。这使得用户在Spring中使用事务时,几乎不用关注实际的事务实现是什么。
3.1 jdbc事务
如果在应用程序中直接使用jdbc来进行持久化,DataSourceTransactionManager会为你处理事务边界。为了使用DataSourceTransactionManager,你需要
使用如下的xml将其装配到应用程序的上下文定义中:
3.2Hibernate事务
如果应用程序是通过Hibernate实现的,那么你需要使用HibernateTransactionManager,对于Hibernate3,需要在Spring 上下文定义中添加如下的<bean>声明
3.3 JPA事务
如果应用程序是通过JPA实现的,需要使用JpaTransactionManager来处理事务
JPA是需要装配一个JPA实体管理工厂(javax.persistence.EntityManagerFactory接口的任意实现),JPATransactionManager将于由工厂所产生的
JPA EntityManager合作来构建事务。
除了将事务应用于JPA操作,JpaTransactionManager还支持将事务应用于简单的JDBC操作之中,这些操作所使用的DataSource与EntityManagerFactory所
使用的DataSource必须相同的。为了做到这一点,JpaTransactionManager必须装配一个JpaDialect的实现。
通过编码添加事务
为了使用TransactionTemplate,你需要实现TransactionCallback接口。
TransactionTemplate 需要注入到service中
4.声明式事务
Spring对声明式事务的支持是通过使用Spring AOP框架实现的。因为事务是在应用程序主要功能之上的系统级服务。
声明事务更好的方式是使用Spring的tx命名空间和@Transactional注解。
4.1 定义事务属性
在Spring中,声明式事务是通过事务属性来定义了。事务属性包含了5各方面
传播行为,隔离级别,回滚规则,是否只读,事务超时。
*传播行为
事务的第一个方面是传播行为。传播行为定义了客户端与被调用方法之间的事务边界。Spring定义了7种不同的传播行为
传播行为常量都在org.springframework.transaction.TransactionDefinition中定义
表中的传播分别对应了CMT管理事务所支持的传播规则。例如Spring的PROPAGATION_REQUIRES_NEW等于CMT的requiresNew.
Spring 还添加了一个CMT中没有的传播行为即PROPAGATION_NESTED
例如,如果一个方法声明了PROPAGATION_REQUIRES_NEW行为,这意味着事务边界与方法自己的边界是一样的。方法在开始执行的时候
启动一个新事务并在方法返回或抛出异常时结束该事务。如果方法具有PROPAGATION_REQUIRED的行为,事务的边界取决于是否已经有事务正在运行
*隔离级别
声明式事务的第二个维度就是隔离级别(isolation level)。隔离级别定义了一个事务可能受其他并发事务影响的程度。另一种考虑隔离级别的方式就是将其想象成事务
对于事务性数据的自私程度。
在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务。并发,虽然是必须的,但可能会导致以下问题
在理想情况下,事务之间是完全隔离的,从而可以防止这些问题的发生。但是完全隔离会导致性能问题,因为它通常会涉及锁定
数据库中的记录(有时候甚至是整张表),侵占性的锁定会阻碍并发性,要求事务互相等待以完成各自的工作。
考虑到完全的隔离会导致性能问题,而且不是所有的应用程序都需要完全隔离,所以有时候应用程序需要在事务上有一定的灵活性。因此,就会有
多种隔离级别
隔离级别都在org.springframework.transaction.TransactionDefinition接口中以常量的方式进行了定义。
ISOLATION_READ_UNCOMMITTED是最高效的事务隔离级别,但是事务隔离的程度最低,事务可能会导致脏读,不可重复读以及幻读。另一个极端则是
ISOLATION_SERIALIZABLE能阻止所有的隔离问题却是最低效的。
注意并不是所有的数据源都支持所有的隔离级别。
*只读
*事务超时
*回滚规则
4.2定义注解驱动的事务
tx命名空间提供了<tx:annotaton-driven />可以通过transaction-manager属性来指定特定的事务管理器
<tx:annotaton-driven />元素高速Spring检查上下文中所有的Bean并查找使用@Transactional注解的Bean,而不管这个注解是用在类还是方法上。
对于每个@Transactional注解的Bean <tx:annotaton-driven />会为它添加事务通知。通知事务的属性通过@Transactional注解的参数来定义的。