在软件开发领域中,全有或全无的操做被称为事务。
java
事务容许你将几个操做组合成一个要么所有发生要么所有不发生的工做单元。
web
事务的4个特性ACID:
spring
原子性(Atomic):事务是由一个或多个活动所组成的一个工做单元。数据库
原子性确保事务中的全部操做所有发生或所有不发生。全部活动成功事务才成功,任意一个活动失败了事务也失败并回滚。
express
一致性(Consistent):一旦事务完成(无论成功仍是失败),系统必须确保它所建模的业务处于一致的状态。后端
隔离性(Isolated):事务容许多个用户对相同的数据进行操做,每一个用户的操做不会与其余用户纠缠在一块儿。并发
事务应该被彼此隔离,避免发生同步读写相同数据的事情(隔离性每每涉及到锁定数据库的行或表)。
框架
持久性(Durable):一旦事务完成,事务的结果应该持久化,这样就能从任何的系统崩溃中恢复过来。分布式
这通常涉及将结果存储到数据库或其余形式的持久化存储中。
性能
若是应用程序只使用一种持久化资源,Spring可使用持久化机制自己所提供的事务性支持,包括了JDBC、Hibernate以及Java持久化API(Java Persistent API,JPA)。
可是若是应用程序的事务跨多个资源,那么Spring会使用第三方的JTA实现来支持分布式事务。
Spring支持编码式事务和声明式事务,编码式事务容许用户在代码中精肯定义事务的边界,而声明式事务(基于AOP)有助于用于将操做与事务规则进行解耦。
Spring并不直接管理事务,而是提供了多种事务管理器,它们将事务管理的职责委托给JTA(Java Transaction API)或其余持久化机制所提供的平台相关的事务实现。
Spring几种常见的事务管理器:
事务管理器 | 使用场景 |
jdbc.datasource.DataSourceTransactionManager | 用于Spring对JDBC抽象的支持,也能够用于使用Mybatis进行持久化的场景 |
org.hibernate3.HibernateTransactionManager |
用于Hibernate3进行持久化 |
orm.jpa.JpaTransactionManager | 用于java持久化API(JPA)进行持久化 |
transaction.jta.JtaTransactionManager |
须要分布式事务或者没有其余的事务管理器知足需求 |
Spring对声明式事务的支持是经过使用Spring AOP框架实现的。这是很天然的一件事,由于事务是在应用程序主要功能之上的系统服务。能够将Spring事务想象成方法”包装“上事务边界的切面。
事务属性包含了5个方面:传播行为、隔离级别、是否只读、事务超时、回读规则。
传播行为
传播行为定义了客户端与被调用方法之间的事务边界。Spring定义了7种不一样的传播行为,都在org.springframework.TransactionDefinition接口中以常量的方式进行了定义。
传播行为 | 含义 |
PROPAGATION_MANDATORY | 表示该方法必须在事务中运行,若是当前事务不存在,则会抛出一个异常 |
PROPAGATION_NESTED | 表示若是当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务能够独立于当前事务进行单独地提交或回滚。若是当前事务不存在,那么其行为与PROPAGATION_REQUIRED同样。(注意,各厂商对这种传播行为的支持是有所差别的。) |
PROPAGATION_NEVER | 表示当前方法不该该运行在事务上下文中,若是当前正有一个事务在运行,则会抛出异常。 |
PROPAGATION_NOT_SUPPORTED | 表示该方法不该该运行在事务中。若是存在当前事务,在该方法运行期间,当前事务将会被挂起,若是使用JTATransactionManager的话,则要访问TransactionManager。 |
PROPAGATION_REQUIRED | 表示当前方法必须运行在事务中。若是当前事务存在,方法将会在该事务中运行,不然,会启动一个新的事务。 |
PROPAGATION_REQUIRES_NEW | 表示当前方法必须运行在它本身的事务中。一个新的事务将会被启动。若是存在当前事务,在该方法执行期间,当前事务会被挂起,若是使用JTATransactionManager的话,则要访问TransactionManager。 |
PROPAGATION_SUPPORTS | 表示当前方法不须要事务上下文,可是若是存在当前事务的话,那么该方法会在这个事务中运行。 |
隔离级别
隔离级别定义了一个事务可能受其余并发事务影响的程度。多个事务并发运行可能致使的问题:脏读、不可重复读、幻读。
隔离级别 | 含义 |
ISOLATION_DEFAULT | 使用后端数据库默认的隔离级别 |
ISOLATION_READ_UNCOMMITTED | 容许读取还没有提交的数据变动。可能会致使脏读、幻读或不可重复读 |
ISOLATION_READ_COMMITED | 容许读取并发事务已经提交的数据。能够组织脏读,可是幻读或不可重复仍有可能发生 |
ISOLATION_REPEATABLE_READ | 对同一字段的屡次读取结果是一致的,除非数据是被本事务本身所修改。能够组织脏读和不可重复读,但幻读仍有可能发生 |
ISOLATION_SERIALIZABLE | 彻底服从ACID的隔离级别,确保组织脏读、不可重复读以及幻读。这是最慢的事务隔离级别。由于它一般是经过彻底锁定事务相关的数据库表来实现的。 |
注意:并非全部的数据源都支持所列的隔离级别。
只读
经过将事务设置为只读,你能够给数据库一个机会,让它应用它认为合适的优化措施。
事务超时
为了使应用程序很好地运行,事务不能运行太长时间。能够在特定的秒数后自动回滚,而不是等待其结束。
回滚规则
这些规则定义了哪些异常会致使事务回滚而哪些不会。默认状况下,事务只有在遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚。
当利用<tx:advice>声明事务的时候,还须要一个事务管理器transactionManager。
<tx:advice>只是定义AOP通知,用于把事务边界通知给方法,可是这只是事务通知,而不是完整的事务性切面。咱们须要定义一个通知器(advisor),才能构成完整的事务性切面,
<!-- 对dataSource 数据源进行事务管理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/> <!-- 事务通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 对insert,update,delete 开头的方法进行事务管理,只要有异常就回滚 --> <tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/> <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/> <!-- select,count开头的方法,开启只读,提升数据库访问性能 --> <tx:method name="select*" read-only="true"/> <tx:method name="count*" read-only="true"/> <!-- 对其余方法 使用默认的事务管理 --> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- 事务 aop 配置 --> <aop:config> <aop:pointcut id="serviceMethods" expression="execution(* com.eliteams.quick4j.web.service..*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/> </aop:config>
在Spring xml中配置<tx:annotation-driven />,能够经过其transactionmanager属性来指定特定的事务管理器。
<tx:annotation-driven>元素告诉Spring检查上下文中全部的Bean并查找使用@Transactional注解的Bean,而无论这个注解是用在类级别上仍是方法级别上。对于每个使用@Transactional注解的Bean,<tx:annotation-driven>会自动为它添加事务通知。