本文共 4581 字,大约阅读时间需要 15 分钟。
1、 事务回顾
事务指的的是逻辑上一组操作,这组要么全都成功,要么全都失败!
事务四大特性
原子性:不可分割,要么都发生,要么都不发生;
一致性:事务的执行前后数据要保持一致;
隔离性:多个用户操作,相互之间事务不能干扰,通过事务的隔离级别做到;
持久性:事务一旦提交,那么数据就会保存持久化了。
2、 Spring事务管理的api
Spring事务管理高层抽象的主要包括3个接口
PlatformTransactionManager:事务管理器
TransactionDefinition事务定义信息(隔离,传播,超时,只读)
TransactionStatus事务具体运行状态(是否提交,保存点,是否新事务)
Spring为不同的持久层框架提供了不同PlatformTransactionManager接口实现
例如在xml中配置如下:
<!-- 配置事务管理器,注意这里的dataSource和SqlSessionFactoryBean的dataSource要一致,不然事务就没有作用了 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"ref="dataSource" />
</bean>
TransactionDefinition接口指定:
· 事务隔离:(4种)当前事务和其它事务的隔离的程度。例如,这个事务能否看到其他事务未提交的写数据?
· 事务传播:(7种)通常在一个事务中执行的所有代码都会在这个事务中运行。但是,如果一个事务上下文已经存在,有几个选项可以指定一个事务性方法的执行行为:例如,简单地在现有的事务中继续运行(大多数情况);或者挂起现有事务,创建一个新的事务。Spring提供EJB CMT中常见的事务传播选项。
· 事务超时:事务在超时前能运行多久(自动被底层的事务基础设施回滚)。
· 只读状态:只读事务不修改任何数据。只读事务在某些情况下(例如当使用Hibernate时),是一种非常有用的优化。
脏读:一个事务读取到另一事务还没有提交的数据,如果这些数据被回滚,那读取到的数据就是无效的!
不可重复读:同一事务
幻读:
Default使用的就是数据库对应的隔离级别:
Mysql默认采用的是Repeatable_read隔离级别
Oracle默认采用的是Read_Committed隔离级别
事务的传播行为7种
事务一般都添加到业务层,
事务的传播行为解决的问题:业务层方法之间的相互调用的问题!
假设有业务层有两个方法:AAA(), BBB()
PROPAGATION_NESTED:AAA()执行完开始调用BBB(),设置保存点,如果BBB成功,一起提交,如果bbb失败,那么可以设置回滚到保存点,或者回滚到最开始。
TransactionStatus接口
案例:
环境准备:
Mysql:
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `money` double DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
代码:spring/transaction/
3、 Spring编程式的事务管理http://blog.sina.com.cn/s/blog_7ffb8dd501014dzh.html
Spring为了简化编程。提供了TransactionTemplate
在本案例中
在AccountSevice中使用TransactionTemplate
TransactionTemplate依赖DataSourceTransactionManager
DataSourceTransactionManager依赖DataSource进行构造
4、 Spring声明式的事务管理,http://blog.sina.com.cn/s/blog_7ffb8dd501014dzx.html
有多种方式:
实现方式一 使用原始TransactionProxyFactoryBean
<!-- 引入外部资源 -->
<context:property-placeholderlocation="classpath:c3p0.properties"/>
<!-- 配置c3p0的连接池 -->
<bean id="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource">
<propertyname="driverClass" value="${c3p0.driverClass}" />
<propertyname="jdbcUrl" value="${c3p0.jdbcUrl}" />
<property name="user"value="${c3p0.user}" />
<propertyname="password" value="${c3p0.password}" />
</bean>
<!-- 配置dao层的类 -->
<bean id="accountDao"class="com.sanshi.spring.transaction.service.AccountDaoImp">
<propertyname="dataSource" ref="dataSource"/>
</bean>
<!-- 配置业务层类 -->
<bean id="accountService"class="com.sanshi.spring.transaction.service.AccountServiceImp">
<propertyname="accountDao" ref="accountDao" />
</bean>
<!-- 配置事务管理器 PlatformTransactionManager的一个实现。用于jdbc,c3p0 ,而hibernate用另外一个实现-->
<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource" ref="dataSource"/>
</bean>
<!--配置业务层的代理 -->
<beanid="accountServiceProxy"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置目标对象 -->
<property name="target"ref="accountService" />
<!-- 注入事务管理器 -->
<propertyname="transactionManager" ref="transactionManager"/>
<!-- 配置事务相关属性 -->
<propertyname="transactionAttributes">
<props>
<!-- prop中的格式
* PROPAGATION : 事务的传播行为
* ISOLATION : 事务的隔离级别
* readOnly : 只读(不能进行更新和添加操作)
* -Exception : 发生哪些异常回滚事务
* +Exception : 发生哪些异常不回滚事务
-->
<propkey="tansfer*">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop>
</props>
</property>
</bean>
然后在使用的时候,使用增强的代理对象
/**
* 必须注入代理类: 因为代理类对应业务类进行了增强
*/
@Resource(name="accountServiceProxy")
privateAccountService accountService;
实现方式二 基于aspectJ的xml配置。需要因为对应jar包
<!-- 配置事务的通知-->
<tx:adviceid="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
propagation: 事务的传播行为
isolation: 事务的隔离级别
read-only: 只读
rollback-for: 发生哪些异常时回滚
no-rollback-for:发生哪些异常异常不回滚
-->
<tx:methodname="tansfer*" propagation="REQUIRED"rollback-for="java.lang.ArithmeticException"/>
</tx:attributes>
</tx:advice>
<!--配置切面 -->
<aop:config>
<!--配置切入点
execution(modifiers-pattern?ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
第一个是修饰符(modifiers-pattern)
第二个是返回值(ret-type-pattern)
第三个方法的包名(declaring-type-pattern)
第四个是方法名(name-pattern)
第五个方法参数(param-pattern)
第六个抛出的异常类型(throws-pattern)
其中 ?对应的值 可以省略
-->
<aop:pointcutexpression="execution(*com.sanshi.spring.transaction.dao.AccountService+.*(..))"id="pointcut1"/>
<!--配置 切面
在pointcut1切入点上。用txAdvice来增强
-->
<aop:advisoradvice-ref="txAdvice" pointcut-ref="pointcut1" />
</aop:config>
使用的时候还是使用原对象,不需要改变什么
实现方式三 基于注解方式
<!-- 开启注解事务 -->
<tx:annotation-driventransaction-manager="transactionManager"/>
在业务层需要使用事务的类或者方法上面加上注解就可以了。
转载地址:https://blog.csdn.net/yangleiGJ/article/details/53095565 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!