Spring学习8-Spring事务管理(编程式事务管理)

一、Spring事务的相关知识
  1、事务是指一系列独立的操作,但在概念上具有原子性。 比如转账:A账号-100,
B账号+100,完成。这两个操作独立是没问题的。 但在逻辑上,要么全部完成,要么一起失败。
  
1)jdbc事务:每个Connection都带有一个事务,只是默认被设置为自动提交。一个连接可以有多个事务。对于JDBC,只有在同一个连接内,才有讨论是否提交的前提。

2)Hibernate事务:本质上也是使用JDBC来处理事务。但是不是直接操作,而是使用Session来操作事务。Session.getTranction();

####事务应该要在service层(也可以叫事务层)进行控制。
为什么用Spring来进行事务控制?
  
如果要手动进行控制事务的话,对于JDBC,service层需要Connection;对于Hibernate,serivice层需要
Session。若一个项目要实现JDBC和Hibernate或其他的互换,我们要做Service层修改很多东西;而且对于Service层来说,他
应该关心的不应该是这些,而是业务逻辑。因此,首先手动控制不能实现组件的替换,其次这些API也不应该出现在service层,但是Spring的
IOC很好的解决了这样的问题。

2、JavaEE传统事务有两种策略:全局事务和局部事务。全局事务由应用服务器管理,需要底层服务器JTA支持(如WebLogic、JBoss等)。局部事务和底层采用的持久化技术有关:当采用JDBC持久化技术时,需要使用Connetion对象来操作事务;而采用Hibernate持久化技术时,需要使用Session对象来操作事务。

全局事务可以跨多个事务性的资源(典型例子是关系数据库和消息队列);使用局部事务,应用服务器不需要参与事务管理,因此不能保证跨多个事务性资源的事务的正确性。当然,实际上大部分应用都使用单一事务性的资源。

Spring事务策略是通过PlatformTransactionManager接口体现的,该接口是Spring事务策略的核心,是一个与任何事务策略分离的接口,随着底层不同事务策略的切换,应用必须采用不同的实现类。结合Spring的IoC容器,可以向该接口注入相关的平台特性。

3、Spring的事务管理,主要有两种方式实现,一种是在代码中编写(编程式事务管理),一种是声明式事务(又可分为AOP式事务管理和注解式事务管理)。在代码中编写要更加细粒度,而很多时候我们只需要简单的事务处理,那就可以用声明式事务。

Spring的事务管理器


事务管理器实现


目标


org.springframework.jdbc.datasource.DataSourceTransactionManager


在JDBC DataSource中管理事务

(须注入数据源datasource 
Bean参数)


org.springframework.orm.hibernate.HibernateTransactionManager


管理Hibernate事务

(须注入SessionFactory
Bean参数)


org.springframework.orm.jdo.JdoTransactionManager


管理JDO事务


org.springframework.transaction.jta.JtaTransactionManager


使用一个JTA管理事务,在一个事务跨越多个资源时必须使用

(无须注入参数)


org.springframework.orm.ojb.PersistenceBrokerTransactionManager


管理Apache的OJB事务

这些事务管理器的的父接口都是PlatformTransactionManager.Spring的事务管理机制是一种典型的策略模式,PlatformTransactionManager
代表事务管理接口(该接口定义了下面所说的三个方法),他并不知道底层如何管理事务,他只要求事务管理的实现类提供开始事务
(getTransaction())、提交事务(commit())、回滚事务(rollback()),但具体如何实现则交给具体的实现类完成——不
同的实现类代表不同的事务管理策略。

说明:

  1、JTA事务管理器无须注入参数,是因为全局事务的JTA资源由JAVA
EE服务器提供,而Spring容器能自行从JAVA EE服务器中获取该事务资源,所以无须使用依赖注入来配置。

  2、当使用JTA全局事务策略时,实际底层须应用服务器支持,而不同的应用服务器所提供的JTA全局事务可能存在细节上的差异,因此实际配置全局事务管理器是可能需要使用JtaTransactionManager的子类,如:OC4JtaTransactionManager(Oracle提供的应用服务器)、WebLogicJtaTransactionManager(Bea提供的WebLogic)、UowJtaTransactionManager(IBM提供的WebSphere)等

二、Spring编程式事务示例

步骤一、编写spring配置文件

下面实例使用DataSourceTransactionManager来管理JDBC事务。

查看Spring的配置信息:(applicationContext.xml):

<?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:p="http://www.springframework.org/schema/p"
    
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="propertyConfig"
        
class="org.springframework.beans.factory.config.

PropertyPlaceholderConfigurer">
        
<property name="location">
            
<value>connect.properties</value>

</property>
    
</bean>
 
    
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">

<property
name="driverClassName">
            
<value>${db.driver}</value>

</property>
        
<property name="url">
            
<value>${db.url}</value>

</property>
        
<property name="username">
            
<value>${db.username}</value>

</property>
        
<property name="password">
            
<value>${db.password}</value>

</property>
    
</bean>
 
    
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">

<property name="dataSource">
            
<ref bean="dataSource" />
        
</property>
    
</bean>
 
    
<!-- JDBC事务管理器 注意:事务管理器传的参数是数据源-->
    
<bean id="transactionManager"
        
class="org.springframework.jdbc.datasource.

      
DataSourceTransactionManager" 
scope="singleton">

<property name="dataSource">
            
<ref bean="dataSource" />
        
</property>
    
</bean>

 
    
<!-- 声明事务模板 -->
    
<bean id="transactionTemplate"
        
class="org.springframework.transaction.support.

  
TransactionTemplate">
        
<property
name="transactionManager">
            
<ref bean="transactionManager"
/>
        
</property>
    
</bean>

 
    
<bean id="bankDao"
class="com.sunflower.dao.BankDaoImp">
        
<property name="jdbcTemplate">
            
<ref bean="jdbcTemplate" />
        
</property>
        
<property
name="transactionTemplate">
            
<ref bean="transactionTemplate"
/>
        
</property>
    
</bean>
 </beans>


面代码中配置了一个org.springframework.transaction.support.TransactionTemplate实例,要
在代码中添加事务,Spring为我们提供了一种方法就是使用TransactionTemplate类。我们要为
TransactionTemplate装配一个TransactionManager,

如果是要配置Hibernate事务,要进行如下配置:(配置一个sessionFactory):

<!-- Hibernate事务管理器  注意:此事务管理器参数是sessionFactory-->

<bean id="transactionManager"
  
class="org.springframework.orm.hibernate3.
  
HibernateTransactionManager"

scope="singleton">

<property
name="sessionFactory">
            
<ref bean="sessionFactory" />
        
</property>
    
</bean>

 如果是要配置JTA事务,要进行如下配置(无须参数):
 <bean
id="
transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"
scope="singleton" >
  </bean>


 步骤二、使用TransactionTemplate进行事务管理:

package com.sunflower.dao;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
 
 import
org.springframework.jdbc.core.JdbcTemplate;
 import
org.springframework.jdbc.core.RowCallbackHandler;
 import
org.springframework.transaction.TransactionStatus;
 import
org.springframework.transaction.support.TransactionCallback;
 import
org.springframework.transaction.support.TransactionTemplate;
 
 import com.sunflower.entity.People;
 
 
 public class BankDaoImp implements BankDao
{
    
private JdbcTemplate jdbcTemplate;
    
private TransactionTemplate transactionTemplate;
 
    
public JdbcTemplate getJdbcTemplate() {
        
return jdbcTemplate;
    
}
 
    
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        
this.jdbcTemplate = jdbcTemplate;
    
}
 
    
public TransactionTemplate getTransactionTemplate() {
        
return transactionTemplate;
    
}
 
    
public void setTransactionTemplate(TransactionTemplate
transactionTemplate) {
        
this.transactionTemplate = transactionTemplate;
    
}
 
    
@Override
    
public double getMoney(final People people) {
        
double money = people.getMoney();
        
// 开始事务,如果出现状况则回滚
        transactionTemplate.execute(new
TransactionCallback<People>()
{
            
@Override
            
public People doInTransaction(TransactionStatus ts) {
                
try {
                    
final People people2 = new People();
                    
// 使用JdbcTemplate进行持久化层操作
                    
String sql = "select money from bank where name = ?";
                    
Object[] params = new Object[] { people.getName() };
                    
// 查询
                    
jdbcTemplate.query(sql, params, new RowCallbackHandler() {
                        
@Override
                        
public void processRow(ResultSet rs)
                                
throws SQLException {
                            
people2.setMoney(rs.getDouble("money"));
                            
System.out.println(people.getName() + "用户还有"
                                    
+ rs.getDouble("money") + "元余款");
                            
System.out.println(people.getName() + "要从账户中取出"
                                    
+ people.getMoney() + "元");
                            
if (people2.getMoney() < people.getMoney()) {
                                
System.out.println("余额不足");
                                
people.setMoney(-1);
                                
return;
                            
}
                        
}
                    
});
 
                    
if (people.getMoney() < 0)
                        
return null;
                    
else {
                        
sql = "update bank set money = ? where name = ?";
                        
Object[] params2 = new Object[] {
                                
people2.getMoney() - people.getMoney(),
                                
people.getName() };
                        
jdbcTemplate.update(sql, params2);
                        
System.out.println("剩余余额:"
                                
+ (people2.getMoney() - people.getMoney()));
                    
}
                
}
                
catch (Exception e) {
                    
ts.setRollbackOnly();
                
}
 
                
// 如果成功,事务被提交
                
return people;
            
}
        
});

 
        
return people.getMoney();
    
}
 }

用TransactionTemplate实例的execute()方法将执行包含在TransactionCallback实例里的代码。如果代码出现
异常,调用TransactionStatus对象的setRollbackOnly()将事务回滚。否则,如果doInTransaction()方法
正常返回,事务将被提交。

时间: 2024-08-26 12:26:57

Spring学习8-Spring事务管理(编程式事务管理)的相关文章

spring事务管理——编程式事务、声明式事务

本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本教程假定您已经掌握了 Java 基础知识,并对 Spring 有一定了解.您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等.本文将直接使用这些概念而不做详细解释.另外,您最好掌握数据库的基础知识,虽然这不是必须. 系统需求 要试验这份教程中的工具和示例,硬件配置需求为:至少带有 512MB 内存(

声明式事务和编程式事务

声明式事务:在配置文件中将事务配置好,通过bean的方式,调用Spring的事务,在程序中不需要做代码性的事务管理,例如commit,backroll等. 编程式事务:需要在代码中加入处理事务的逻辑,可能需要在代码中显示调用beginTransaction(),commit(),rollback()等事务相关的方法,例如在执行a方法时候需要事务处理,需要在a方法开始时候开启事务,处理完后.在方法结束时候,关闭事务. 事务都是为了保证数据的一致和完整,保证整个操作的原子性(即不可分割性,事务要么全

spring ----编程式事务和声明式事务

一. 事务 事务管理对于企业应用而言是非常重要的,事务的存在保证了用户的每一次操作都是可靠的,当用户操作出现异常时也不至于破坏了后台的数据.例如银行的自动取款机,万一你在转账的时候出现了异常,事务机制会保证你后台的数据还是出异常操作之前的数据,也就是是你出异常的这些操作失效. 事务就是一组由于逻辑上紧密关联而合并成一个整体(工作单元)的多个数据库操作,这些操作要么都执行,要么都不执行. 银行转账操作:开启事务,就是保证转账的操作要么都执行,要么都不执行. 如果在你的账户减去转账金额后出现异常,不

全面分析 Spring 的编程式事务管理及声明式事务管理--转

开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本教程假定您已经掌握了 Java 基础知识,并对 Spring 有一定了解.您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等.本文将直接使用这些概念而不做详细解释.另外,您最好掌握数据库的基础知识,虽然这不是必须. 系统需求 要试验这份教程中的工具和示例,硬件配置需求为:至少带

分析 Spring 的编程式事务管理及声明式事务管理(转)

开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本教程假定您已经掌握了 Java 基础知识,并对 Spring 有一定了解.您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等.本文将直接使用这些概念而不做详细解释.另外,您最好掌握数据库的基础知识,虽然这不是必须. 系统需求 要试验这份教程中的工具和示例,硬件配置需求为:至少带

Spring 的编程式事务管理及声明式事务管理

本文将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. Spring 事务属性分析 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作过程中机器突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过取款机一样,以保

Spring事务管理的实现方式:编程式事务与声明式事务

本文转载于本人另一博客[http://blog.csdn.net/liaohaojian/article/details/70139151] 1.上篇文章讲解了Spring事务的传播级别与隔离级别,以及分布式事务的简单配置,点击回看上篇文章 2.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理) Spring实现编程式事务,依赖于2大类,分别是上篇文章提到的PlatformTransactionManager,与模版类TransactionTemplate(推荐使用).下面分别详细介

Spring事务管理的另一种方式--TransactionTemplate编程式事务管理简单入门

1, 一直以来, 在用Spring进行事物管理时, 只知道用声明式的策略, 即根据不同的数据源, 配置一个事物管理器(TransactionManager), 通过配置切面(PointCut)应用到相应的业务方法上或者直接在方法上加@Ttransactional注解. 这种事务管理使用起来比较简单,但个人感觉灵活性欠缺了点. 2, 最近看公司项目代码, 发现有位同事在他的模块了用了另外一种事务管理方式, 查了一下,TransactionTemplate是编程式事务管理.需要自己手动在每个业务方法

全面分析 Spring 的编程式事务管理及声明式事务管理

转自:http://www.open-open.com/lib/view/open1414310646012.html 关于本教程 本教程将深切讲授 Spring 庞杂而丁壮夜的事务治理功用,包括编程式事务和声明式事务.经由进程对本教程的进修,您将可以理解 Spring 事务治理的实质,并无邪运用之. 先决前提 本教程假定您已掌控了 Java 根蒂根抵常识,并对 Spring 有一定意见.您还需求具有根抵的事务治理的常识,好比:事务的界说,隔离级其他概念,等等.本文将直接行使这些概念而不做具体正