spring的事务管理
Spring事务管理基于底层数据库本身的事务处理机制
- 事务具备ACID四种特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)
原子性:事务执行要么全部成功,要么全部失败,不存在第三种状态
一致性:事务完成后,数据库中的变化按期待的那样完成,保证了事务的原子性却不一定能保证一致性
隔离性:并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间,某个并发事务所做的修改必须与任何其他并发事务所做的修改隔离,事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据
持久性:只要事务成功结束,它对数据库所做的更新就必须永久保存下来
- 事务的传播
多个事务对方法进行调用,如何定义方法间事务的传播,Spring定义了以下几种传播行为(此处只列出了两种.):
propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是Spring默认的选择。
propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
- 脏读、不可重复读:
脏读指a事务正在访问数据,并且对数据进行了修改,但这种修改还没有提交到数据库中,这时b事务也访问了这个数据,然后使用了这个数据。因为这个数据的修改还没有被a事务提交,故b事务读取到的这个数据就是脏数据,对脏数据所做的操作是不正确的。
不可重复读:在a事务内,需要多次读同一数据,在a事务还没有执行结束时,b事务也访问了该数据,那么在a事务中的两次读取数据之间,由于b事务的修改使a事务两次读到的数据可能不一样,这样就发生了在一个事物内两次连续读到的数据是不一样的,此为不可重复读。
- 事务的隔离级别
- read uncommited:最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据
- read commited:保证一个事物提交后,数据才能被另外一个事务读取,另外一个事务不能读取该事物未提交的数据。
- serializable:这是花费最高代价但最可靠的事务隔离级别,事务被处理为顺序执行,可防止脏读,不可重复读
- Spring实现事务的3种方式
- 基于 TransactionProxyFactoryBean的声明式事务管理
- 基于 @Transactional 的声明式事务管理
- 基于Aspectj AOP配置事务
此3种方式均需要在xml配置文件里进行相关的配置;第二种方式的缺点是在很多需要添加事务处理的地方需要在方法前一个个加事务,第三种方法通过AOP的处理可以批量地对方法添加事务处理;
//接口 public interface UserService(){ public void addSinger(); } //实现类 public class UserServiceImpl implements UserService{ public void addUser(){ //此处为实现逻辑..... } }
- 基于 TransactionProxyFactoryBean的声明式事务管理:(xml配置文件主要部分内容)
<bean id="userService" class="com.test.serviceImpl.UserServiceImpl"></bean> <!-- 注册数据源 C3P0 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 事务管理器 --> <bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 事务代理工厂 --> <!-- 生成事务代理对象 --> <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="myTracnsactionManager"></property> <property name="target" ref="userService"></property> <property name="transactionAttributes"> <props> <!-- key 指明哪些方法需要进行事务管理 ISOLATION_DEFAULT 事务的默认隔离级别 PROPAGATION_REQUIRED 传播行为 --> <prop key="add*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop> </props> </property> </bean>
- 基于 @Transactional 的声明式事务管理(xml配置文件主要部分内容)
<bean id="userService" class="com.test.serviceImpl.UserServiceImpl"></bean> <!-- 注册数据源 C3P0 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 事务管理器 --> <bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 启用事务注解 --> <tx:annotation-driven transaction-manager="myTracnsactionManager"/> 而实现类变为: @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,rollbackFor=Exception.class) public class UserServiceImpl implements UserService{ public void addUser(){ //此处为实现逻辑..... } }
- 基于Aspectj AOP配置事务(xml配置文件主要部分内容)
bean id="userService" class="com.test.serviceImpl.UserServiceImpl"></bean> <!-- 注册数据源 C3P0 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 事务管理器 --> <bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 切入点配置 --> <aop:config> <aop:pointcut expression="execution(* *..service.*.*(..))" id="point"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="point"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="myTracnsactionManager"> <tx:attributes> <!-- 为连接点指定事务属性 --> <tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED"/> </tx:attributes> </tx:advice>

浙公网安备 33010602011771号