spring 编程式事务

8 篇文章 0 订阅
一、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()方法正常返回,事务将被提交。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值