Spring的事务处理

主要讲事务的基本概念和处理方法

前面Spring提供的AOP就是实现了事务处理。

(一)事务的概念

定义:事务就是一连串步骤依次执行的过程,这些步骤都是同时成功和同时失败的。

事务处理有两个关键概念:提交(Commit)和回滚(Rollback)

提交就是在一个事务内部全部执行成功了,就可以提交。

回滚就是在一个事务内部只要有一个步骤失败了,那这个事务回滚,所有已经执行和未经执行的步骤都会回到事务开始的状态。

 

事务的4个特性:ACID

原子性:Atomicity 一致性:Consistency 隔离性:Isolation 持久性:Durabulity

1、原子性:

原子性说明事务是一个整体,这个整体一荣俱荣,一损俱损的。保证事务是否完全完成。

2、一致性:

说明事务开始和事务结束,其逻辑状态都是一致的。比如去银行取钱,一个是账户余额,一个是交易流水,在事务开始之前,逻辑状态应该是原先有100元,没有进行取款就不存在交易流水。到事务结束,假设取款50元,那按照业务逻辑来说应该是账户余额还剩50元,且同时产生了一笔交易流水。这样不管是在事务开始还是结束,其逻辑状态都是一致的,没有问题。如果在事务结束,账户余额还剩50元,但是没有交易流水,那这个就在事务结束的时候逻辑状态就不一致了,不符合事务的一致性。所以事务的一致性确保了逻辑的正确性。当处理事务的过程中,有任何一个步骤失败,都应该将所有事务中涉及的数据都恢复到事务还未开始的状态。

3、隔离性

确保一个事务在执行过程中,对另一个事务是不可见的,这样就不会存在两个事务同时去修改同一个数据。

4、持久性

一旦事务提交了,事务对数据的改变的动作是持久的,一直保存在系统中,可以保存在数据库的事务日志中。如果想恢复数据,可以使用数据库的事务日志。

 

(二)传统事务处理的3种方式:

关系型数据库的事务处理、传统的JDBC事务处理、分布式事务处理

1、关系型数据库的事务处理:

Begin Transaction //通知事务开始处理

//事务处理的过程

Commit/Rollback

End Transaction//事务结束,一并执行

事务之间的隔离程度:Isolation Level

read uncommited:不管事务是否提交均支持访问

read commited:只允许读取已经提交的记录

repeatable read:只允许读取在事务开始之前拍的快照,事务开始后的不管是提交的还是没提交的记录都不读不到

大多数默认 read commited

 

2、传统的JDBC的事务处理

 

package com.gc.acion;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.sql.DataSource;

public class JDBCTransaction {
	Connection conn = null;
	PreparedStatement ps = null;
	private DataSource dataSource;
	
	public void setDataSource(DataSource dataSource){
		this.dataSource = dataSource;
	}
	
	public void startTransaction(){
		try {
			//通过数据源获取数据库连接池链接
			conn = dataSource.getConnection();
			//不自动提交
			conn.setAutoCommit(false);
			
			String sql1 = "delete from tbstudent";
			String sql2 = "insert into tbstudent value(001,'wangyj')";
			//创建执行对象1
			ps = conn.prepareStatement(sql1);
			//执行sql1
			ps.executeUpdate();
			//创建执行对象2
			ps = conn.prepareStatement(sql2);
			//执行sql2
			ps.execute();
			//提交
			conn.commit();
			
		} catch (SQLException e) {
			if(conn != null){
				try {
					//事务处理失败,回滚
					conn.rollback();
				} catch (SQLException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}finally{
			try {
				//关闭采用栈的方式,后进先关
				if(ps != null){
					ps.close();
				}
				
				if(conn != null){
					conn.close();
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}


3、分布式事务处理

 

针对多个数据库进行事务处理(比如前两个是银行内用同一个数据库完成的转账,而分布式针对的是跨行之间的转账,涉及两个数据库甚至多个数据库的事务处理)

分布式事务需要多个不同的事务管理器合作。

 

(三)Spring的事务处理

Spring提供了两种事务处理方式:编程式事务处理、声明式事务处理

 

1、先来了解一下Spring的事务处理

Spring的事务处理是基于动态AOP机制,为了实现动态AOP,Spring在默认情况下会使用Java动态代理机制。动态代理机制要求代理对象必须要实现一个接口。

Spring事务中心接口是org.springframework.transaction.PlatformTransactionManager;

Spring事务处理常用的一些接口源码:

PlatformTransactionManager:

 

package org.springframework.transaction;

public abstract interface PlatformTransactionManager {
	public abstract TransactionStatus getTransaction(
			TransactionDefinition paramTransactionDefinition)
			throws TransactionException;

	public abstract void commit(TransactionStatus paramTransactionStatus)
			throws TransactionException;

	public abstract void rollback(TransactionStatus paramTransactionStatus)
			throws TransactionException;
}


TransactionDefinition:

 

 

package org.springframework.transaction;

public abstract interface TransactionDefinition {
	public static final int PROPAGATION_REQUIRED = 0;
	public static final int PROPAGATION_SUPPORTS = 1;
	public static final int PROPAGATION_MANDATORY = 2;
	public static final int PROPAGATION_REQUIRES_NEW = 3;
	public static final int PROPAGATION_NOT_SUPPORTED = 4;
	public static final int PROPAGATION_NEVER = 5;
	public static final int PROPAGATION_NESTED = 6;
	public static final int ISOLATION_DEFAULT = -1;
	public static final int ISOLATION_READ_UNCOMMITTED = 1;
	public static final int ISOLATION_READ_COMMITTED = 2;
	public static final int ISOLATION_REPEATABLE_READ = 4;
	public static final int ISOLATION_SERIALIZABLE = 8;
	public static final int TIMEOUT_DEFAULT = -1;

	public abstract int getPropagationBehavior();

	public abstract int getIsolationLevel();

	public abstract int getTimeout();

	public abstract boolean isReadOnly();

	public abstract String getName();
}

 

 

 

 

 


TransactionStatus:

 

package org.springframework.transaction;

import java.io.Flushable;

public abstract interface TransactionStatus extends SavepointManager, Flushable {
	public abstract boolean isNewTransaction();

	public abstract boolean hasSavepoint();

	public abstract void setRollbackOnly();

	public abstract boolean isRollbackOnly();

	public abstract void flush();

	public abstract boolean isCompleted();
}


2、编程式事务处理(手动编写代码进行事务管理)

 

Spring通过org.springframework.transaction.support.TransactionTemplate;来提供编程式事务的处理。TransactionTemplate是无状态且线程安全的。

 

package org.springframework.transaction.support;

import java.lang.reflect.UndeclaredThrowableException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.TransactionSystemException;

public class TransactionTemplate extends DefaultTransactionDefinition implements
		TransactionOperations, InitializingBean {
	protected final Log logger = LogFactory.getLog(super.getClass());
	private PlatformTransactionManager transactionManager;

	public TransactionTemplate() {
	}

	public TransactionTemplate(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}

	public TransactionTemplate(PlatformTransactionManager transactionManager,
			TransactionDefinition transactionDefinition) {
		super(transactionDefinition);
		this.transactionManager = transactionManager;
	}

	public void setTransactionManager(
			PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}

	public PlatformTransactionManager getTransactionManager() {
		return this.transactionManager;
	}

	public void afterPropertiesSet() {
		if (this.transactionManager == null)
			throw new IllegalArgumentException(
					"Property 'transactionManager' is required");
	}

	public <T> T execute(TransactionCallback<T> action)
			throws TransactionException {
		if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
			return ((CallbackPreferringPlatformTransactionManager) this.transactionManager)
					.execute(this, action);
		}

		TransactionStatus status = this.transactionManager.getTransaction(this);
		Object result;
		try {
			result = action.doInTransaction(status);
		} catch (RuntimeException ex) {
			rollbackOnException(status, ex);
			throw ex;
		} catch (Error err) {
			rollbackOnException(status, err);
			throw err;
		} catch (Throwable ex) {
			rollbackOnException(status, ex);
			throw new UndeclaredThrowableException(ex,
					"TransactionCallback threw undeclared checked exception");
		}
		Object result;
		this.transactionManager.commit(status);
		return result;
	}

	private void rollbackOnException(TransactionStatus status, Throwable ex)
			throws TransactionException {
		this.logger.debug(
				"Initiating transaction rollback on application exception", ex);
		try {
			this.transactionManager.rollback(status);
		} catch (TransactionSystemException ex2) {
			this.logger.error(
					"Application exception overridden by rollback exception",
					ex);
			ex2.initApplicationException(ex);
			throw ex2;
		} catch (RuntimeException ex2) {
			this.logger.error(
					"Application exception overridden by rollback exception",
					ex);
			throw ex2;
		} catch (Error err) {
			this.logger.error(
					"Application exception overridden by rollback error", ex);
			throw err;
		}
	}
}


如上源码可以看到:

 

1、需要TransactionTemplate提供PlatformTransactionManager的实例。前面说到PlatformTransactionManager的实现类很多。

2、要实现TransactionTemplate,只需要调用execute方法。在该方法中要用到TransactionCallback的doInTransaction()方法

3、所以基于第2点要实现TransactionCallback接口,doInTransaction并且在doInTransaction()进行数据库操作。

4、如果操作成功,则提交this.transactionManager.commit(status);

5、如果操作失败,则回滚rollbackOnException(status, ex);

6、result是事务执行结果。

 

通过TransactionTemplate实现编程式事务的处理实例:

 

package com.gc.acion;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

public class HelloDAO {
	private DataSource dataSource;
	private PlatformTransactionManager transactionManager;
	
	//通过依赖注入中的set注入来完成管理
	public void setDataSource(DataSource dataSource){
		this.dataSource = dataSource;
	}
	
	public void setTransactionManager(PlatformTransactionManager transactionManager){
		this.transactionManager = transactionManager;
	}
	
	public Object create(String msg){
		TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
		Object result = transactionTemplate.execute(new TransactionCallback(){
			//重写doInTransaction方法,进行具体数据库操作
			@Override
			public Object doInTransaction(
					TransactionStatus paramTransactionStatus) {
				// TODO Auto-generated method stub
				Connection conn = null;
				PreparedStatement ps = null;
				int  objResult = -1;
				//数据库事务处理
				try {
					conn = dataSource.getConnection();
					ps = conn.prepareStatement("insert into tbstudent values(001, 'wangyj')");
					objResult = ps.executeUpdate();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return objResult;
			}
		});
		
		return result;
	}
}

 


因为前面使用了set依赖注入的方式,所以要有xml配置。

 

<!-- 设定dataSource -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>oracle.jdbc.driver.OracleDriver</value>
		</property>
		<property name="url">
			<value>jdbc:oracle:thin:@127.0.0.1:1521:oral</value>
		</property>
		<property name="username">
			<value>hr</value>
		</property>
		<property name="password">
			<value>hr1234</value>
		</property>
	</bean>
	
	<!-- 设定transactionManager -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	
	<!-- 设定事务处理实现类 HelloDAO-->
	<bean id="HelloDAO" class="com.gc.acion.HelloDAO">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
	</bean>

 


这样在HelloDAO中create方法对数据进行处理的时候,Spring会自动对这个操作使用事务处理,不用在写commit和rollback方法了,

 

因为TransactionCallback还有一个无参数返回的实现类TransactionCallbackWithoutResult,所以还有另一个方法实现:

 

package com.gc.acion;

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

public class HelloDAO {
	private DataSource dataSource;
	private PlatformTransactionManager transactionManager;
	
	//通过依赖注入中的set注入来完成管理
	public void setDataSource(DataSource dataSource){
		this.dataSource = dataSource;
	}
	
	public void setTransactionManager(PlatformTransactionManager transactionManager){
		this.transactionManager = transactionManager;
	}
	
	public Object create(String msg){
		TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
		Object result = transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(
					TransactionStatus paramTransactionStatus) {
				// TODO Auto-generated method stub
				JdbcTemplate jdbctemplate = new JdbcTemplate(dataSource);
				jdbctemplate.update("insert into tbstudent values(001, 'wangyj')");
			}
		});
		
		return result;
	}
}


xml配置文件依赖注入同上。

 

 

3、声明式事务处理(事务处理放在配置文件中处理)

声明式事务处理主要借助于AOP的实现,所以要引入两个相关jar包:

aopalliance-1.0.jar和cglib-2.1.3.jar

 

Java代码:

 

package com.gc.acion;

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;

public class ByeDAO {
	private DataSource dataSource;
	private JdbcTemplate jdbcTemplate;
	
	//通过set方式依赖注入
	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
		jdbcTemplate = new JdbcTemplate(dataSource);
	}
	
	//这里不处理事务,事务的处理都放在配置文件中
	public void create(DataSource dataSource){
		jdbcTemplate.update("insert into tbstudent values(001, 'wangyj')");
	}
}

 

xml配置:

 

<!-- 设定dataSource -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>oracle.jdbc.driver.OracleDriver</value>
		</property>
		<property name="url">
			<value>jdbc:oracle:thin:@127.0.0.1:1521:oral</value>
		</property>
		<property name="username">
			<value>hr</value>
		</property>
		<property name="password">
			<value>hr1234</value>
		</property>
	</bean>
	
	<!-- 设定transactionManager -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	
	<!-- 事务处理实现类ByeDAO -->
	<bean id="ByeDAO" class="com.gc.acion.ByeDAO">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!-- 声明式事务处理代理类 -->
	<bean id="ByeDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
		<property name="target">
			<ref bean="ByeDAO"/><!-- 被代理类 -->
		</property>
		<property name="transactionAttributes">
			<props key="creat*">PROPAGATION_REQUIRED</props><!-- 对ByeDAO类中的create方法进行事务管理,如果当前没有事务就新建一个事务 -->
		</property>
	</bean>

 

 

 

transactionAttributes 属性:

PROPAGATION

 

事务传播行为类型

说明

PROPAGATION_REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。

PROPAGATION_SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

 

 

小结:

 

事务的基础知识和相关概念

传统事务的处理:关系型数据库,JDBC,分布式数据库

Spring事务处理:编程式事务处理和声明式事务处理

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值