Spring事务之事务控制方式
2016-04-13 19:32
363 查看
一、编程式事务控制
JDBC的事务管理在Spring2.0下有两种编程式的实现PlatformTransactionManager
TransactionTemplate
1、PlatformTransactionManager 事务管理器
package org.springframework.transaction; public abstract interface PlatformTransactionManager { //根据事务定义TransactionDefinition,获取事务 public abstract TransactionStatus getTransaction(TransactionDefinition paramTransactionDefinition) throws TransactionException; //提交事务 public abstract void commit(TransactionStatus paramTransactionStatus) throws TransactionException; //回滚事务 public abstract void rollback(TransactionStatus paramTransactionStatus) throws TransactionException; }
(1)TransactionDefinition : 事务的一些基础信息,如超时时间、隔离级别、传播属性等
(2)TransactionStatus : 事务的一些状态信息,如是否是一个新的事务、是否已被标记为回滚
在使用的过程中常常使用它的最终实现类DataSourceTransactionManager。
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable{ } public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean{ }
具体实现步骤:
1. 实例化的时候,需要用个数据源作参数
2. 建立事务的定义,使用DefaultTransactionDefinition类,直接new个新的就可以了
3. 调用DefaultTransactionDefinition类的setPropagationBehavior方法,参数是TransactionDefinition的常量,例如PROPAGATION_REQUIRED等。
4. 在使用到具体的SQL操作之前,创建一个TransactionStatus类的实例: TransactionStatus status = transactionManager.getTransaction(def)。
其中,transactionManager是DataSourceTransactionManager类的实例,def是DefaultTransactionDefinition的实例
5. 之后使用具体的SQL操作,发生异常了,就使用transactionManager.rollback(status)
6. 正常操作的话,就使用transactionManager.commit(status)
举例:
public void insert(){ PlatformTransactionManager tran = new DataSourceTransactionManager(dataSource); DefaultTransactionDefinition def = new DefaultTransactionDefinition();//事务定义类 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status = tran.getTransaction(def);//返回事务 try { JdbcTemplate template = new JdbcTemplate(dataSource); template.update("Insert into userinfo(username,password) values('aaaaa','bbbbb')"); template.update("Insert into userinfo(username,password) values('ccccc','ddddd')"); tran.rollback(status); } catch (Exception e) { tran.rollback(status); e.printStackTrace(); } }
由于Spring容器底层采用ThreadLocal存储事务当前线程的Connection,所以DataSourceTransactionManager中操作Connection对象和JdbcTemplate中操作的Connection是同一个对象(详情见另一博文:《Spring中事务之如何保证同一个Connection对象》),因此能够DataSourceTransactionManager能够代理管理JdbcTemplate的事务。
PlatformTransactionManager源码详细分析见:
http://www.07net01.com/2015/05/842465.html
2、TransactionTemplate 事务模板
TransactionTemplate模板类用于简化事务管理,事务管理由模板类定义,而具体操作需要通过TransactionCallback回调接口或TransactionCallbackWithoutResult回调接口指定,通过调用模板类的参数类型为TransactionCallback或TransactionCallbackWithoutResult的execute方法来自动享受事务管理。
TransactionTemplate模板类使用的回调接口:
TransactionCallback:通过实现该接口的“T doInTransaction(TransactionStatus status) ”方法来定义需要事务管理的操作代码;
TransactionCallbackWithoutResult:继承TransactionCallback接口,提供“void doInTransactionWithoutResult(TransactionStatus status)”便利接口用于方便那些不需要返回值的事务操作代码。
具体步骤:
1. 在具体的SQL语句操作签,实例化它:
TransactioinTemplate transactionTemplate = new TransactionTemplate(trasactionManager);
2. 然后就是具体的SQL操作,不过写起来有点复杂:
transactionTemplate.execute( new TransactionCallback() { public Object doInTransaction(TransactionStatus status) { // 这里执行SQL的操作 // 发生异常的时候status.setRollbackOnly(),正常的时候直接返回结果 } } );
3.如果没有返回值,可以使用TransactionCallbackWithoutResult类。里面的方法调用一样,只不过用了TransactionCallbackWithoutResult的匿名继承。
举例:
public void update(){ DataSourceTransactionManager tran = new DataSourceTransactionManager(dataSource); TransactionTemplate tranTemplate = new TransactionTemplate(tran); tranTemplate.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { int retInt = 0; try { JdbcTemplate template = new JdbcTemplate(dataSource); template.update("udpate userinfo set password = 'mbbbb' where username = 'aaaaa' "); template.update("udpate userinfo set password = 'mdddd' where username = 'ccccc' "); retInt = 1; } catch (Exception e) { status.setRollbackOnly();//通知回滚 e.printStackTrace(); } return new Integer(retInt); } }); }
二、XML配置(AOP)事务控制
在Spring配置文件中配置如下<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.gjt.mm.mysql.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test?userUnicode=true&characterEncoding=UTF-8" /> <property name="username" value="root" /> <property name="password" value="5" /> <!-- 连接池启动时的初始值 --> <property name="initialSize" value="1" /> <!-- 连接池的最大值 --> <property name="maxActive" value="500" /> <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 --> <property name="maxIdle" value="2" /> <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 --> <property name="minIdle" value="1" /> </bean> <!-- 配置DataSourceTransactionManager事务 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 配置通知 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="*" read-only="true" propagation="NOT_SUPPORTED" /> </tx:attributes> </tx:advice> <!-- 配置事务管理切面 --> <aop:config> <aop:pointcut id="transactionPointcut" expression="execution(* com.haiwi.service.impl.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" /> </aop:config> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="bookService" class="com.ufgov.fm.server.serviceimpl.BookServiceImpl"> <property name="jdbcTemplate" ref="jdbcTemplate" /> </bean> </beans>
下面是Spring中Propagation类的事务属性详解:
REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
service代码如下
package com.haiwi.service; public interface BookService { public void insertBook(); } package com.haiwi.service.impl; import org.springframework.jdbc.core.JdbcTemplate; import com.haiwi.service.BookService; public class BookServiceImpl implements BookService { JdbcTemplate jdbcTemplate ; public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void insertBook() { jdbcTemplate.update("update book set book_type='编程语言' where cate = '001'"); jdbcTemplate.update("update book set book_type='数据库' where cate = '002'"); jdbcTemplate.update("update book set book_type='操作系统' where cate = '003'"); } }
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- 模拟Spring的简单实现
- Spring整合WebSocket应用示例(上)
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- springmvc 发送ajax出现中文乱码的解决方法汇总
- SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
- struts2 spring整合fieldError问题
- spring的jdbctemplate的crud的基类dao
- 读取spring配置文件的方法(spring读取资源文件)
- Spring Bean基本管理实例详解
- java实现简单美女拼图游戏
- 详解Java的Spring框架中的事务管理方式
- 解析Java的Spring框架的BeanPostProcessor发布处理器