spring事务

    Spring支持两种方式实现事务:编程式事务、声明式事务。

【编程式事务】

      编程式事务使用TransactionTemplate或者直接使用底层的PlatformTransactionManager

      以Hibernate为例:

1.添加事务的业务层类

 

[java] view plain copy
  1. <span style="font-family:Comic Sans MS;">package com.bjpowernode.usermgr.manager;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import org.hibernate.Session;  
  6.   
  7. import com.bjpowernode.usermgr.domain.Log;  
  8. import com.bjpowernode.usermgr.domain.User;  
  9. import com.bjpowernode.usermgr.util.HibernateUtils;  
  10.   
  11. public class UserManagerImpl implements UserManager {  
  12.   
  13.     @Override  
  14.     public void addUser(User user) {  
  15.         Session session = null;  
  16.         try {  
  17.             // 获取session  
  18.             session = HibernateUtils.getSessionFactory().getCurrentSession();  
  19.   
  20.             // 开始事务  
  21.             session.beginTransaction();  
  22.   
  23.             // 添加用户  
  24.             session.save(user);  
  25.   
  26.             // 添加日志־  
  27.             Log log = new Log();  
  28.             log.setType("操作日志");  
  29.             log.setTime(new Date());  
  30.             log.setDetail("***");  
  31.             LogManager logManager = new LogManagerImpl();  
  32.             logManager.addLog(log);  
  33.             Integer.parseInt("sfjsklf");  
  34.   
  35.             // 提交事务  
  36.             session.getTransaction().commit();  
  37.         } catch (Exception e) {  
  38.             e.printStackTrace();  
  39.             session.getTransaction().rollback();  
  40.         }  
  41.     }  
  42.   
  43.   
  44. }</span>  

 

2.一些配置

 

[html] view plain copy
  1. <span style="font-family:Comic Sans MS;"><!DOCTYPE hibernate-configuration PUBLIC  
  2.     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
  3.     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
  4.   
  5. <hibernate-configuration>  
  6.     <session-factory>  
  7.         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>  
  8.         <property name="hibernate.connection.url">jdbc:mysql://localhost/spring_hibernate_1?characterEncoding=utf-8</property>  
  9.         <property name="hibernate.connection.username">root</property>  
  10.         <property name="hibernate.connection.password">123456</property>  
  11.         <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>  
  12.         <property name="hibernate.show_sql">true</property>  
  13.         <property name="hibernate.hbm2ddl.auto">update</property>  
  14.   
  15.         <property name="hibernate.current_session_context_class">thread</property>  
  16.   
  17.         <mapping resource="com/bjpowernode/usermgr/domain/User.hbm.xml" />  
  18.         <mapping resource="com/bjpowernode/usermgr/domain/Log.hbm.xml" />  
  19.     </session-factory>  
  20. </hibernate-configuration></span>  

 

3.HibernateUtils类:

 

[java] view plain copy
  1. <span style="font-family:Comic Sans MS;">package com.bjpowernode.usermgr.util;  
  2.   
  3. import org.hibernate.Session;  
  4. import org.hibernate.SessionFactory;  
  5. import org.hibernate.cfg.Configuration;  
  6.   
  7. public class HibernateUtils {  
  8.   
  9.     private static SessionFactory factory;  
  10.       
  11.     private HibernateUtils() {  
  12.     }  
  13.       
  14.     static {  
  15.         try {  
  16.             Configuration cfg = new Configuration().configure();  
  17.             factory = cfg.buildSessionFactory();  
  18.         }catch(Exception e) {  
  19.             e.printStackTrace();  
  20.             throw new java.lang.RuntimeException(e);  
  21.         }     
  22.     }  
  23.       
  24.     public static SessionFactory getSessionFactory() {  
  25.         return factory;  
  26.     }  
  27.       
  28.     public static Session getSession() {  
  29.         return factory.openSession();  
  30.     }  
  31.       
  32.     public static void closeSession(Session session) {  
  33.         if (session != null) {  
  34.             if (session.isOpen()) {  
  35.                 session.close();  
  36.             }  
  37.         }  
  38.     }  
  39. }  
  40. </span>  

4.User类和Log类略

 

【声明式事务】

      声明式事务是建立在AOP之上的,本质是对方法前后进行拦截,然后在目标方法开始之前创建一个事务,在执行完方法之后根据执行情况提交事务或者回滚事务。

声明式事务可以用两类方式添加,第一是针对小型项目,就是@注解方式,在方法之前添加事务。第二也是比较普遍用的,在xml配置事务添加的条件,这样比较方便,而且事务是指定同意规则下添加的。

一、@Transactional注解

1.源码如下:

 

[java] view plain copy
  1. <span style="font-family:Comic Sans MS;">/* 
  2.  * Copyright 2002-2006 the original author or authors. 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package org.springframework.transaction.annotation;  
  18.   
  19. import java.lang.annotation.Documented;  
  20. import java.lang.annotation.ElementType;  
  21. import java.lang.annotation.Inherited;  
  22. import java.lang.annotation.Retention;  
  23. import java.lang.annotation.RetentionPolicy;  
  24. import java.lang.annotation.Target;  
  25.   
  26. import org.springframework.transaction.TransactionDefinition;  
  27.   
  28. /** 
  29.  * Describes transaction attributes on a method or class. 
  30.  *  
  31.  * <p> 
  32.  * This annotation type is generally directly comparable to Spring's 
  33.  * {@link org.springframework.transaction.interceptor.RuleBasedTransactionAttribute} 
  34.  * class, and in fact {@link AnnotationTransactionAttributeSource} will directly 
  35.  * convert the data to the latter class, so that Spring's transaction support 
  36.  * code does not have to know about annotations. If no rules are relevant to the 
  37.  * exception, it will be treated like 
  38.  * {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute} 
  39.  * (rolling back on runtime exceptions). 
  40.  *  
  41.  * @author Colin Sampaleanu 
  42.  * @author Juergen Hoeller 
  43.  * @since 1.2 
  44.  * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute 
  45.  * @see org.springframework.transaction.interceptor.RuleBasedTransactionAttribute 
  46.  */  
  47. @Target({ ElementType.METHOD, ElementType.TYPE })  
  48. @Retention(RetentionPolicy.RUNTIME)  
  49. @Inherited  
  50. @Documented  
  51. public @interface Transactional {  
  52.   
  53.     // 可选的事务传播行为设置  
  54.     Propagation propagation() default Propagation.REQUIRED;  
  55.   
  56.     // 可选的事务隔离级别设置  
  57.     Isolation isolation() default Isolation.DEFAULT;  
  58.   
  59.     // 事务超时时间设置  
  60.     int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;  
  61.   
  62.     // 读写或只读事务,默认读写  
  63.     boolean readOnly() default false;  
  64.   
  65.     // 导致事务回滚的异常类数组,必须继承自Throwable  
  66.     Class<? extends Throwable>[] rollbackFor() default {};  
  67.   
  68.     // 导致事务回滚的异常类名字数组,必须继承自Throwable  
  69.     String[] rollbackForClassName() default {};  
  70.   
  71.     // 不会导致事务回滚的异常类数组,必须继承自Throwable  
  72.     Class<? extends Throwable>[] noRollbackFor() default {};  
  73.   
  74.     // 不会导致事务回滚的异常类名字数组,必须继承Throwable  
  75.     String[] noRollbackForClassName() default {};  
  76.   
  77. }</span>  

 

2.用法:

      @Transactional注解可以作用于接口、接口方法、类、类方法上,但是一般我们都会注解在类或者类方法上,一般是业务层的类和方法,并且@Transactional注解只被应用到public方法上。

3.示例:

 

[java] view plain copy
  1. <span style="font-family:Comic Sans MS;">//①注解在类上,这是类中所有public方法都具有该类型的事务  
  2. @Transactional  
  3. public class StudentBeanImpl extends BaseBeanImpl<Student> implements  
  4.         StudentBean {  
  5.   
  6.     //①注解在方法上,只有来自外部的方法调用才会被捕获并且引起事务行为,本类中的方法调用会被忽略事务行为  
  7.     @Transactional  
  8.     @Override  
  9.     public boolean saveStudents(Student student, String databaseName,  
  10.             String authorityDataBaseName, String companyNumber) {  
  11.         boolean userflag = false;  
  12.         try {  
  13.             // 1. 将数据存入基础库*********************************************  
  14.             // 2.将数据存入authority库,大段代码略******************************  
  15.             // 3.将数据存入cloud库,大段代码略**********************************  
  16.         } catch (Exception e) {  
  17.             e.printStackTrace();  
  18.             return false;  
  19.         }  
  20.         return userflag;  
  21.     }  
  22.   
  23.   
  24. }</span>  

 

二、xml配置,配置也有好几种方式,下面选用使用tx标签配置的拦截器

      除了一些项目中用到的类的注入以及数据库连接的配置外,其他的一些公共行为都在applicationContext-common.xml中进行配置,代码如下:

 

[html] view plain copy
  1. <span style="font-family:Comic Sans MS;"><?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <beans xmlns="http://www.springframework.org/schema/beans"  
  4.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.          xmlns:aop="http://www.springframework.org/schema/aop"  
  6.          xmlns:tx="http://www.springframework.org/schema/tx"  
  7.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  8.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd  
  9.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  
  10.     <!-- 配置SessionFactory -->  
  11.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  12.         <property name="configLocation">  
  13.             <value>classpath:hibernate.cfg.xml</value>  
  14.         </property>  
  15.     </bean>  
  16.       
  17.     <!-- 定义事务管理器 -->  
  18.     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  19.         <property name="sessionFactory">  
  20.             <ref bean="sessionFactory"/>            
  21.         </property>  
  22.     </bean>  
  23.       
  24.     <!-- 使用AOP配置com.bjpowernode.usermgr.manager包下所有方法都使用该事务配置 -->  
  25.     <aop:config>  
  26.         <aop:pointcut id="allManagerMethod" expression="execution(* com.bjpowernode.usermgr.manager.*.*(..))"/>  
  27.         <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice"/>  
  28.     </aop:config>  
  29.       
  30.     <!-- 事务的传播特性 -->    
  31.     <tx:advice id="txAdvice" transaction-manager="transactionManager">  
  32.         <tx:attributes>  
  33.             <tx:method name="add*" propagation="REQUIRED"/>  
  34.             <tx:method name="del*" propagation="REQUIRED"/>  
  35.             <tx:method name="modify*" propagation="REQUIRED"/>  
  36.             <tx:method name="*" propagation="REQUIRED" read-only="true"/>  
  37.         </tx:attributes>  
  38.     </tx:advice>  
  39. </beans></span>  

 

【事务传播特性】

1.        PROPAGATION_REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启

2.        PROPAGATION_SUPPORTS:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行

3.        PROPAGATION_MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。

4.        PROPAGATION_REQUIRES_NEW:总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。

5.        PROPAGATION_NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的事务。

6.        PROPAGATION_NEVER:总是非事务地执行,如果存在一个活动事务,则抛出异常

7.        PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动事务,

    则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

 

【事务的隔离级别】

1.        ISOLATION_DEFAULT:这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.

     另外四个与JDBC的隔离级别相对应

2.        ISOLATION_READ_UNCOMMITTED:这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。

     这种隔离级别会产生脏读,不可重复读和幻像读。

3.        ISOLATION_READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据

4.        ISOLATION_REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。

    它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。

5.        ISOLATION_SERIALIZABLE这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。

     除了防止脏读,不可重复读外,还避免了幻像读。

posted on 2017-11-30 23:34  忘-乐  阅读(104)  评论(0)    收藏  举报

导航