事务管理
Spring事务管理的接口
Spring框架中有个spring-tx-x.x.x.RELEASE的JAR包,就是Spring提供事务管理的依赖包。在该JAR包中的org.springframework.transaction包中,有如下三个重要的接口。
- PlatformTransactionManager
用于管理事务的接口
- TransactionDefinition
用于定义事务的规则
- TransactionStatus
描述事务的状态信息
PlatformTransactionManager
- TransactionStatus getTransaction(TransactionDefinition definition):用于获取事务的状态信息
- void commit(TransactionStatus status):提交事务
- void rollback(TransactionStatus status):回滚事务
当持久层采用不同的 技术时,需要使用该接口不同的实现类。
- org.springframework.jdbc.datasource.DataSourceTransactionManager:数据源为JDBC的事务管理器
- org.springframework.orm.hibernate4.HibernateTransactionManager:数据源为hibernate的事务管理器
- org.springframework.transaction.jta.JtaTransactionManager:配置全局的事务管理器
TransactionDefinition
- String getName():事务对象名称
- int getIsolationLevel():事务隔离级别
- int getTimeout():事务的超时时间
- boolean isReadOnly():事务是否只读
- int getPropagationBehavior():事务传播行为,它有如下几个值。默认状态为REQUIRED
值 | 描述 |
---|---|
REQUIRED | 如果当前方法处于事务环境中,则直接使用该方法,否则开启一个新事务 |
SUPPORTS | 如果当前方法处于事务环境中,则使用当前事务,否则不使用事务 |
MANDATOR | 调用该方法的线程必须处于事务环境中,否则报错 |
REQUIRES_NEW | 要求方法在新的事务环境中执行。如果已处于某个事务环境,先暂停当前事务,启动新的事务执行该方法,如果不在事务环境中,开启一个新的事务后执行方法 |
NOT_SUPPORTED | 总是以非事务状态执行。如果处于事务环境中,暂停当前事务,然后执行方法 |
NEVER | 不支持当前事务。如果调用该方法的线程处于事务环境中,报异常 |
NESTED | 在事务环境中,依旧启动一个新事务,并且方法嵌套在事务里执行。不在事务环境中,启动一个新事务,执行方法 |
TransactionStatus
- void flush():刷新事务
- boolean hasSavepoint():获取是否存在保存点
- boolean isCompleted():事务是否完成
- boolean isNewTransaction():是否为新事务
- boolean isRollbackOnly():事务是否回滚
- void setRollbackOnly():设置事务回滚
基于XML方式的声名式事务管理
基于XML方法的事务管理,将DAO层方法作为切入点,然后将事务通知做为一个切面, 最后植入进入。具体框架如下:
<!--编写事务通知
transaction-manager:指定事务管理器
-->
<tx:advice id="txAdvice" tarnsaction-manager="transactionManager">
<tx:attributes>
<!--
name:*表示任意方法
propagtion:事务传播行为
isolation:事务隔离级别
read-only:事务是否只读
-->
<!--指定用于哪些方法-->
<tx:method name="*" propagtion="REQUIRED" isolation="DEFAULT" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--基于AspectJ编写AOP,对目标形成代理-->
<aop:config>
<!--不需要配置通知类型-->
<!--切入点-->
<aop:pointcut expression="execution(* com.syl.jdbc.*.*(..))" id="txPointCut" />
<!--切面,将事务通知作为切面-->
<aop:advice advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
示例——转账业务
-
创建DAO层接口
-
DAO层接口实现类,实现转账业务
-
配置applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- JdbcTemplate -->
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 将JdbcTemplate注入AccountDaoImpl中 -->
<bean id="accountDao"
class="com.syl.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!-- 给数据源配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 编写事务通知,将此通知作为切面织入切入点 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 哪些方法需要事务管理 -->
<tx:method name="*" propagation="REQUIRED"
isolation="DEFAULT" read-only="false" />
</tx:attributes>
</tx:advice>
<!-- 编写aop -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut expression="execution(* com.syl.dao.*.*(..))"
id="txPointCut"/>
<!-- 切面 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
- 测试
基于注解式的事务管理
基于Anonation方式的事务管理需要做如下两件事
- Spring容器中注册事务注解驱动
<tx:annotation-driven transaction-manager="transactionManager" />
- @Transaction注解,在类上注解表示整个类的方法都使用该事务管理器,在方法上注解,表示仅对此方法有效。@Transaction参数如下:
参数 | 说明 |
---|---|
value | 指定需要使用的事务管理器,默认为"",别名为transactionManager |
transactionManager | 指定事务的限定符值。 |
isolation | 隔离级别,默认Isolation.DEFAULT |
propagation | 事务传播行为 |
read-only | 是否只读。默认false |
-
修改applicationContext.xml
-
修改AccountDaoImpl
-
测试
@syl 2021/09/02 周四 22:26 回宿舍