您的位置:首页 > 编程语言 > Java开发

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'");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息