一. 事务特性
事务管理是企业级应用程序开发中必不可少的技术,主要用来确保数据的完整性和一致性。
而所谓的事务,其实就是一系列的动作,它们被当做一个单独的工作单元,这些动作要么全部完成,要么全部不起作用。在事务中,有四个关键属性(ACID):
原子性(atomicity): 事务是一个原子操作,由一系列动作组成,事务的原子性确保动作要么全部完成要么完全不起作用。
一致性(consistency): 一旦所有事务动作完成,事务就被提交,数据和资源就处于一种满足业务规则的一致性状态中。
隔离性(isolation): 可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏。
持久性(durability): 一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。通常情况下,事务的结果被写到持久化存储器中。
二. Spring中的事务管理
作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层。而应用程序开发人员不必了解底层的事务管理 API,就可以使用 Spring 的事务管理机制。Spring 既支持编程式事务管理,也支持声明式的事务管理。
1. 编程式事务管理
将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式管理事务时,必须在每个事务操作中包含额外的事务管理代码。
2. 声明式事务管理
大多数情况下比编程式事务管理更好用,它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点,可以通过 AOP 方法模块化,Spring通过 Spring AOP框架支持声明式事务管理。
三. Spring中的事务管理器
Spring 从不同的事务管理API中抽象了一整套的事务机制,开发人员不必了解底层的事务API,就可以利用这些事务机制,有了这些事务机制,事务管理代码就能独立于特定的事务技术了。
1. 事务传播机制
只需要在方法上加 @Transactional 注解,这时候就有问题了。Spring对事务的控制,是使用 aop 切面实现的,我们不用关心事务的开始、提交、回滚。
2. 传播机制生效条件
Spring 是使用aop来代理事务控制,是针对于接口或类的,所以在同一个service类中两个方法的调用,传播机制是不生效的。
四. 事务案例
了解了以上这些关于事务的特性,接下来我们再通过一个案例来看看事务怎么实现。既然要管理和操作数据库,就离不开数据表,所以下面我们先来设计两个表。
1. 转帐功能
帐户表:account
字段名 | 类型 | 说明 | 描述 |
id | 主键ID | ||
name | 姓名 | ||
balance | 余额 | ||
cardid | 卡号 |
2. 商品下单功能
商品表:product
字段名 | 类型 | 说明 | 描述 |
id | 主键ID | ||
name | 商品名称 | ||
count | 数量 | ||
price | 价格 |
五. Spring声明式注解事务
接下来是对事务进行必要的代码实现,这里可以采用XML配置的方式进行实现。
1.spring_core.xml
在Spring环境中创建一个spring_core.xml配置文件,对事务进行必要的配置。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
2. @Transactional注解声明式地管理事务
在xml文件中进行配置之后,我们就可以直接利用@Transactional注解进行事务管理了。
@Transactional注解可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
虽然@Transactional 注解可以作用于接口、接口方法、类以及类方法上,但Spring不建议在接口或者接口方法上使用该注解,@Transactional 注解应该只被应用到public方法上,这是由Spring AOP的本质决定的。如果你在protected、private或者默认可见性的方法上使用 @Transactional注解,它会被忽略,也不会抛出任何异常。
六. Spring 事务回滚机制
Spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。Spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。
默认配置下,Spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。
常用运行时异常:空指针异常、除数不为0异常等。
七. 小结
从理论上来说,事务应该彼此完全隔离,以避免并发事务所导致的问题。然而,那样会对性能产生极大的影响,因为事务必须按顺序运行。
在实际开发中,为了提升性能,事务应以较低的隔离级别运行。
转载请注明:XAMPP中文组官网 » 基于Spring体系,事务的特性和实现机制