spring事务管理

关于事务:
逻辑上的一组操作,要么全部成功,要么全部失败。
特性:
原子性:不可分割的工作单位,都发生或都不发生
一致性:事务前后数据完整性要保持一致,不会丢数据
隔离性:多个用户并发访问数据库,用户之间互不干扰,通过设置事务隔离级别来达到
持久性:事务提交后,对数据库数据的改变时永久性的

spring事务接口:
PlatformTransactionManager 事务管理器:
有不同的实现类,根据不同的持久层框架选择不同的实现类。譬如:spring jdbc或iBatis框架--DataSourceTransactionManager,Hibernate--HibernateTransactionManager,其他还有jpa、jta等等

TransactionDefinition 事务定义(隔离级别,传播行为,超时,只读):
定义了很多常量:ISOLATION_*:事务隔离级别常量,PROPAGATION_*:事务传播常量,TIME_OUT:超时信息。
定义了很多方法,用以获取这些信息。

事务隔离级别--若没有隔离性会引发的问题:
脏读--一个事务读取了另一个事务改写但还未提交的数据,如果事务回滚那么数据时无效的;不可重复读--在一个事务内,多次读取同一数据,在这个事务第一次读取后,另一个事务修改该数据,那么在该事务再次读取该数据时发现不同了;幻读--一个事务读取几行记录后,另一个事务插入记录,那么在后来的查询中,第一个事务会发现之前没有的记录。
脏读是由于读取未提交记录;不可重复读和幻读是由于两个事务并没有互相独立
spring提供四种隔离级别:READ_UNCOMMITED(允许读取还未提交的改变了的数据,可能导致脏读、幻读、不可重复读),READ_COMMITED(允许并发事务已提交后读取,可能导致幻读和不可重复读),REPEATABLE_READ(对相同字段多次读取是一致的,可能导致幻读),SERIALIZABLE(完全符合隔离级别,不会发生误读,但最慢,通过完全锁定在事务中涉及到的数据完成),另外还有default级别,就是使用的数据库的默认隔离级别。mysql默认隔离级别是repeatable_read

事务的传播行为:
用于解决业务层方法的相互调用问题。web应用三层架构:web--service--dao,一般事务是定义在service方法中的,一个service包含多个dao,这几个dao作为一个事务。但是业务复杂后,多个servcie互相调用的情况。之所以叫做事务传播,是希望外层service方法中的事务能够传递到内层service方法。spring中事务传播行为分为三类--七种:
譬如两个service方法a()和b():但是a()中又调用了b()  a(){b();...},以下属性都是作用于方法b()的
第一类:如果a()中有事务,b()会使用a()中的事务,否则:
PROPAGATION_REQUIRED:a()中没有事务,b()创建一个事务
PROPAGATION_SUPPORTS:a()中没有事务,b()中不使用事务
PROPAGATION_MANDATORY:a()中没有事务,则抛异常
第二类:如果a()中有事务,则将a()中事务挂起,b()不在a()的事务中运行
PROPAGATION_REQUIRES_NEW:如果a()中有事务,b()则新建一个事务,和a()不在同一个事务中
PROPAGATION_NOT_SUPPORTED:b()以非事务方式运行,如果a()有事务则挂起当前事务
PROPAGATION_NEVER:b()以非事务方式运行,如果a()有事务则抛异常
第三类:
PROPAGATION_NESTED:a()和b()中的事务都作为新方法中的嵌套事务,a()中有保存点

TransactionStatus 事务具体运行状态
根据事务定义,由事务管理器进行管理,管理过程中产生的状态保存在事务运行状态中

spring支持两种方式的事务管理:
--编程时事务管理:实际很少使用,通过TransactionTemplate手动管理事务
--xml配置声明式事务:推荐使用,通过aop实现,侵入性小

具体实例:
引入相关jar包,jdbc、tx以及和核心包
1、新建service方法,dao方法
2、编辑spring的applicationContext.xml文件
a、引入properties文件:<context:property-placeholder location="classpath:xx.properties">,之后就可以直接在xml中直接引用${}引用properties中的key-value了
b、配置连接池,配置datasource,c3p0的连接池,设置驱动类名、jdbc url、用户名、密码等
c、配置service和dao层的bean文件
3、dao层编码
a、继承JdbcDaoSupport,bean文件中注入连接池--datasource,这样就可以直接在dao中使用模板了
b、写sql吧:
string sql = "update ..."
this.getJdbcTemplate().update(sql, param1,param2);
4、service层代码
a、注入dao bean以及调用dao的方法
譬如说有这样一个service层的反复
public void transfer() {
     accountDAO.outMoney("xxx",200); // xxx账户转出200
     accountDAO.inMoney("yyy",200); // yyy账户转入200
}

接下来,如何使用事务呢???
编程式事务管理,不建议使用了,麻烦而且有代码侵入,使用DataSourceTransactionManager(事务管理器),TransactionTemplate(为了简化代码,会使用模板使用事务管理器)
声明式事务管理:
方式一:基于TransactionProxyFactoryBean,并不经常使用,因为要为每个需要事务管理的bean都配置TransactionProxyFactoryBean。
1、基于aop完成,需要引入aop相关jar包:aop原始jar包和aop与spring整合的aop-springjar包
2、配置事务管理器:<bean id="transactionManager" class="DataSourceTransactionManager.java"><property name="datasource" ref="xx"></bean> 什么样的dao框架决定注入什么样的事务管理器
3、配置业务层代理,因为是要对业务层方法进行事务管理,所以要生成业务方法的代理类,这个代理类在将原业务方法前后增加事务的代码,以完成事务管理
//生成代理类的代理工厂
<bean id="accountServiceProxy" class="TransactionProxyFactoryBean">
     <!-- 目标类,哪些类要生成代理对象,执行事务 -->
     <property name="target" ref="accountServcie">
     <!-- 注入事务管理器 -->
     <property name="transactionManager" ref="transactionManager">
     <!-- 注入事务属性,是一个属性对象,而不是普通的类,直接使用<props>标签注入 -->
     <property name="transactionAttributes">
          <props>
               <prop key="transfer"> // key是类中的方法名,对不同的方法配置不同的事务属性,属性(传播行为,隔离级别等,用逗号分隔)写在<prop>标签内部
               </prop>
          </props>
     </property>
</bean>
4、在使用service方法的地方,注入代理类(注意不是原service方法类)transactionProxyFactoryBean

方式二:基于aspectJ XML方式
1、基于aspectJ,aspectJ是第三方aop开发框架,引入aspectJ原始jar和aspect与spring整合的包aspectJ-spring的jar
2、配置事务管理器:<bean id="transactionManager" class="DataSourceTransactionManager.java"><property name="datasource" ref="xx"></bean> 什么样的dao框架决定注入什么样的事务管理器
3、配置事务的增强
<tx:advice id="txAdvice" transaction-manager="transactionManager">
     <tx:attributes>
          <tx:method name="transfer" propagation="">
     </tx:attributes>
</tx:advice>
4、配置切面
<aop:config>
     <!-- 配置切入点 -->
     <aop:pointcut expression="execution(* xxx.AccountService+.*(..))" id="pointcut1"> // 支持通过表达式来定义切入点,切入点指的是在哪里进行增强,这里是AccountService的任意方法任意参数
     <!-- 配置切面 -->
     <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"> // 切面是指的是增强,这里表示在pointcut1切入点,进行txAdvice这个增强
</aop:config>
5、这种方式会对原有类进行增强,直接是用原有类即可

方式三:基于注解的方式,配置和使用都非常简单
1、配置事务管理器:<bean id="transactionManager" class="DataSourceTransactionManager.java"><property name="datasource" ref="xx"></bean> 什么样的dao框架决定注入什么样的事务管理器
2、开启注解事务
<tx:annotation-driven transaction-manager="transactionManager" />
然后在需要使用事务的地方添加注解,譬如:
@Transactional(propagation=Propagation.REQUIRED,Isolation=xxx)
public void transfer
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值