Spring的事务管理三大组件
1事务管理
一个数据库事务是一个被视为单一的工作单元的操作序列。这些操作应该要么完整地执行,要么完全不执行。
开发中,很多复杂的事务要分步进行,但它们组成了一个整体,要么整体生效,要么整体失效。这种思想反映到数据库上,就是多条SQL语句,要么所有执行成功,要么所有执行失败。
数据库事务有严格的定义,它必须同时满足4个特征:原子性,一致性,隔离性,持久性,简称ACID。每个特征的含义如下:
-
原子性:事务应该当作一个单独单元的操作,这意味着整个序列操作要么是成功,要么是失败的。事务中的任何一个数据库操作失败,已经执行的任何操作都必须撤销。让数据库返回到初始
-
一致性:事务操作成功后,数据库所处的状态和它的业务规则是一致的。即数据不会被 破坏。如A帐号转账200元给B帐号,不管操作成功与否,A帐号和B帐号的存款总和是不变的;
-
隔离性:在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对对方产生干扰,准确的说,并非要求做到完全无干扰。数据库规定了多种事务隔离级别,不同的隔离级别对应不同的干扰程序。隔离级别越高,数据一致性就好,但并发性就越差。
-
持久性:一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。
2两种类型的事务管理
Spring 支持两种类型的事务管理:
-
编程式事务管理:这意味着你在编程的帮助下有管理事务。这给了你极大的灵活性,但却很难维护。
-
声明式事务管理:这意味着你从业务代码中分离事务管理。你仅仅使用注释或 XML 配置来管理事务。
3 Spring对事务管理的支持
Spring为事务管理提供了一致的编程模版,在高层次建立了统一的事务抽象。也就是说,不管是选择SpringJDBC,Hibernate,JPA还是Mybatis,Spring都可以让用户统一的编程模型进行事务管理
1.事务管理的关键抽象
在Spring事务管理的抽象层主要包括3个接口,分别是
-
PlatformTransactionManager
-
TransactionDefinition
-
TransactionStatus
这三个接口都位于org.springframework.transaction包中;
2.TransactionDefinition
此接口中定义了Spring兼容的事务属性,这些属性对事务管理控制的若干方面进行了配置
-
事务隔离
-
事务传播
-
事务超时
-
只读状态
TransactionDefinition接口是事务定义(描述)的对象,它提供了事务相关信息获取的方法,其中包括五个操作,具体如下。
-
String getName():获取事务对象名称。
-
int getIsolationLevel():获取事务的隔离级别。
-
int getPropagationBehavior():获取事务的传播行为。
-
int getTimeout():获取事务的超时时间。
-
boolean isReadOnly():获取事务是否只读。
3.TransactionStatus
TransactionStatus 代表事务的具体运行状态,事务管理器可以通过该接口获取事务运行期的状态信息。其中包含六个操作,具体如表 2 所示。
名称 | 说明 |
---|---|
void flush() | 刷新事务 |
boolean hasSavepoint() | 获取是否存在保存点 |
boolean isCompleted() | 获取事务是否完成 |
boolean isNewTransaction() | 获取是否是新事务 |
boolean isRollbackOnly() | 获取是否回滚 |
void setRollbackOnly() | 设置事务回滚 |
4.PlatformTransactionManager
PlatformTransactionManager 接口是 Spring 提供的平台事务管理器,用于管理事务。该接口中提供了三个事务操作方法,具体如下。
-
TransactionStatus getTransaction(TransactionDefinition definition):该方法根据事务定义信息从事务环境中返加一个已存在的事务,或者创建一个新的事务,并用TransactionStatus描述这个事务的状态。
-
void commit(TransactionStatus status):根据事务的状态提交事务。如果事务状态已经被标识为rollback-only,则该方法将执行一个回滚事务操作。
-
void rollback(TransactionStatus status):将事务回滚。当commit()方法抛出异常时,rollback()方法会被 隐式调用。
在项目中,Spring 将 xml 中配置的事务详细信息封装到对象 TransactionDefinition 中,然后通过事务管理器的 getTransaction() 方法获得事务的状态(TransactionStatus),并对事务进行下一步的操作。
5.事务管理器的实现类
Spring将事务管理委托给底层具体的持久化实现框架来完成。因此,Spring为不同的持久化框架提供了PlatformTransactionManager接口的实现类,
事务 | 说明 |
---|---|
org.springframework.orm.jpa. JpaTransactionManager | 使用JPA进行持久化时,使用该事务管理器 |
org.springframework.orm.hibernateX. HibernateTransactionManager | 使用HibernateX.0(X可为3,4,5)进行持久化时,使用此事务管理器 |
org.springframework.jdbc.datasource. DataSourceTransactionManager | 使用SpringJDBC或Mybatis等基于DataSource数据源的持久化持久时,使用此事务管理器 |
org.springframework.orm.jdo. JdoTransactionManager | 使用JDO进行持久化时,使用此事务管理器 |
org.springframework.transaction.jta. JtaTransactionManager | 具有多个数据源的全局事务使用该事务管理器(不管采用何种持久化技术) |
这些事务管理器都是对特定事务实现框架的代理,这样就可以通过Spring所提交的高级抽象对不同类的事务实现实现使用相同的方式进行管理,而不用关系具体的实现细节
要实现事务管理,首先要在Spring中配置好相应的事务管理器,为事务管理器指定数据资源及一此其它事务管理控制属性。
4事务管理器的配置
声明式事务举例:
思路:
-
定义数据源(如已存在,忽略此步骤)
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="root"></property> <property name="password" value="tiger"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/books"></property> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="initialPoolSize" value="1"></property> </bean>
-
spring的事务管理是通过事务管理器来实现的,即我们应该先创建一个事务管理器对象;
<!-- 创建datasource事务管理器对象 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
-
如果实现Annotation控制事务,需要增加tx命名空间,并开启annotation驱动;
<!--使用用annotation来控制事务,@Transactional将起作用--> <tx:annotation-driven transaction-manager="transactionManager"/>
-
通过Annotation控制时,可以在Service的方法中加入@Transactional注解
@Transactional public void buy(int accountid,int bookid) { //插入订单; bookDao.insertOrder(accountid, bookid); //获得价格 Integer i=bookDao.getPrice(bookid); System.out.println(i); //更新数量; bookDao.updateRemain(accountid, i); }
坑提示:mysql的数据引擎中innodb支持事务,memory与myisam并不支持。