【Spring学习笔记】15 spring的事务管理接及转账案例添加事务

2018.5.28
一、spring事务管理接口

1、spring的TransactionManager接口
在不同平台,操作事务的代码各不相同,因为spring提供了一个TransactionManager接口:
DataSourceTransactionManager 用于JDBC的事务管理
HibernateTransactionManager 用于hibernate的事务管理
jpaTransactionManager 用于Jpa的事务管理 ----------------------------Hibernate接口的实现----->Jpa是一个接口一个标准,参考hibernate
【Spring学习笔记】15 spring的事务管理接及转账案例添加事务
2、spring中TransactionManager接口的定义(源码)
package com.lu.spring.service;

import java.sql.Connection;

public interface TransactionDefinition {
/**
* 绝大部分情况下只用前两个
*/
int PROPAGATION_REQUIRED = 0;//支持当前事务,如果不存在,就新建一个。insert select 支持当前操作为查询操作 适应于增删改

int PROPAGATION_SUPPORTS = 1;//支持当前事务,如果不存在,就不使用事务。 select select 查。

int PROPAGATION_MANDATORY = 2;//支持当前事务,如果不存在,就抛出异常。

int PROPAGATION_REQUIRES_NEW = 3;//如果有事务存在,挂起当前事务,创建一个新的事务

int PROPAGATION_NOT_SUPPORTED = 4;//以非事务方式运行,如果有事物存在,就抛出异常

int PROPAGATION_NEVER = 5;//以非事务方式运行,如果有事务存在,就抛出异常

int PROPAGATION_NESTED = 6;//如果有事务存在,则嵌套事务执行

int ISOLATION_DEFAULT = -1;//默认级别,MySQL:默认为PRPEATABLE_READ级别 SQLSERVER:默认为READ_COMMITTED

int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;

int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;

int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;

int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;

int TIMEOUT_DEFAULT = -1;//默认是-1,不超时,单位是秒
//事务的传播级别
int getPropagationBehavior();
//事务的隔离级别
int getIsolationLevel();
//事务超出时间
int getTimeout();
//是否只读
boolean isReadOnly();

String getName();

}

二、为转账案例添加事务

一、配置XML方式
1、转账事务的名称空间
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd" >
3、配置事务管理器
<!-- 事务管理器 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
4、配置通知
查询为supports 且为只读事务read-only 增加效率
<!-- 通知 自己定义的不能用name 只能用ID-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 传播行为 -->
<!-- name:你要应用到哪个service方法中 -->
<!-- REQUIRED 支持当前事务,如果不存在,就新建一个 -->
<tx:method name="transfer" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="create*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="edit*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED"/>
<tx:method name="select*" propagation="SUPPORTS"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="query*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="search*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
5、配置切面
<!-- 切面:通知织入切入点-->
<aop:config>
<!-- 切入点 -->
<aop:pointcut expression="execution(* com.lu.spring.service..*.*(..))" id="txPointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
二、注解方式
不需要配置通知和切面但更多内容入侵代码当中
<!-- 事务管理器 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解事务管理 -->
<tx:annotation-driven/>
但是需要在service层中事务上定义注解@Transactional,可以在类上全局注解事务管理,但是事务传播行为全是默认值
所以遇到特殊的增删改和查都要定义上各自的propagation(传播)。
@Service("accountService")
@Transactional
public class AccountServiceImpl implements AccountService {
@Resource(name="accountDao")
private AccountDao accountDao;
@Override
@Transactional(propagation=Propagation.REQUIRED,readOnly=false,isolation=Isolation.REPEATABLE_READ)
public void transfer(Integer from, Integer to, Double money) {
accountDao.subMoney(from, money);
//int a= 9/0;//无事务的用例 报异常之后只有from减钱,to不加钱。
accountDao.addMoney(to, money);
}

}