`

spring学习笔记:spring事务管理

    博客分类:
  • java
阅读更多

数据库事务的4个特性:
原子性(atomic): 都成功或者都失败;
一致性(consistency):事务操作之后,数据库所处的状态和业务规则是一致的;比如a,b账户相互转账之后,总金额不变;
隔离性(isolation):操作中的事务不相互影响;
持久性(durability):事务提交后被持久化到数据库.
数据并发产生的问题:
脏读:一个事物a读到了另一个事务b未提交的数据,则b回滚后,a读取的数据无效;
不可重复读:一个事物a第二次读到了另一个事务b修改的数据;
幻读:在统计数据的事务a两次统计的数据不一致(因为有其他事务新增数据)
第一类丢失更新:a事务回滚覆盖了b事务提交的数据;
第二类丢失更新:a事务覆盖了b事务提交的数据.
事物隔离级别: READ_UNCOMMITED, READ_COMMITED, REPEATABLE_READ, SERIALIZABLE; 一般情况下READ_COMMITED足够了.
spring事务管理相关的接口:
TransactionDefinition:代表一个事物,描述了事务的隔离级别, 超时时间,事务是否只读, 传播规则等等;
TransactionStatus:描述事物的状态;
PlatformTransactionManager:事务管理器接口, 只定义了3个方法:getTransaction()获取事务的状态; commit();rollback();
事务管理器的实现类有多种,根据具体的持久层框架的不同而不同;
spring中的事务传播行为的种类:
PROPAGATION_REQUIRED: 如果当前没有事务,就创建一个事务;如果已经存在事务,则加入事务;
PROPAGATION_SUPPORTS: 如果已经存在事务,则加入事务;如果没有事务,则以非事务的方式执行;
PROPAGATION_MANDATORY: 使用当前事务, 如果没有, 则抛出异常;
PROPAGATION_REQUIRED_NEW: 新建事务,如果当前有事务, 则挂起;
PROPAGATION_NOT_SUPPORTED:以非事务的方式执行, 如果当前有事务, 则挂起;
PROPAGATION_NEVER:以非事务的方式执行, 如果当前有事务,则抛出异常;
使用spring声明式的事务管理:
大多数情况下,事务会放在services层,spring声明式的事务管理中,需要做以下的工作:
1 把dao,service注入到spring容器(这些dao, service不涉及事务);
2 需要注入一个transactionManager(它需要dataSource);
3 通过TransactionProxyFactoryBean为目标对象(需要事务的dao, service等等)提供事务增强,产生增强后的代理对象.
看代码:
先添加一个CompanyService,
view plaincopy to clipboardprint?
package services;  
import java.util.List;  
import model.Company;  
import dao.hibernate.CompanyDao;  
 
public class CompanyService {  
 private CompanyDao companyDao;  
 public CompanyDao getCompanyDao() {  
  return companyDao;  
 }  
 public void setCompanyDao(CompanyDao companyDao) {  
  this.companyDao = companyDao;  
 }  
 public void insertCompany(Company c){  
  //some security check  
  companyDao.save(c);  
  //some updates  
 }  
 public void deleteCompany(int id){  
  //some security check  
  companyDao.deleteById(id);  
  // some updates  
 }  
 public void updateCompany(Company c){  
  companyDao.save(c);  
 }  
 public List list(){  
  return companyDao.list();  
 }  

package services;
import java.util.List;
import model.Company;
import dao.hibernate.CompanyDao;

public class CompanyService {
 private CompanyDao companyDao;
 public CompanyDao getCompanyDao() {
  return companyDao;
 }
 public void setCompanyDao(CompanyDao companyDao) {
  this.companyDao = companyDao;
 }
 public void insertCompany(Company c){
  //some security check
  companyDao.save(c);
  //some updates
 }
 public void deleteCompany(int id){
  //some security check
  companyDao.deleteById(id);
  // some updates
 }
 public void updateCompany(Company c){
  companyDao.save(c);
 }
 public List list(){
  return companyDao.list();
 }
}

 

它调用dao组件执行crud.事务控制一般都放在这一层.

spring事务管理第一种配置方式:为每个目标bean配置一个代理
view plaincopy to clipboardprint?
<bean id="companyDao" class="dao.hibernate.CompanyDaoImpl"> 
 <property name="hibernateTemplate" ref="hibernateTemplate" /> 
</bean> 
<!-- 需要被增强的bean通常命名为xxxxTarget --> 
<bean id="companyServiceTarget" class="services.CompanyService"> 
 <property name="companyDao" ref="companyDao" /> 
</bean> 
<!-- 事务管理器 --> 
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
 <property name="dataSource" ref="dataSource" /> 
</bean> 
<!-- 被代理之后的service,它具有事务功能,程序中我们就使用它 --> 
<bean id="companyService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
 <!-- 事务管理器 --> 
 <property name="transactionManager" ref="txManager" /> 
 <!-- 需要被代理的目标 --> 
 <property name="target" ref="companyServiceTarget" /> 
 <!-- optimize可选,true代表使用CGLib, false代表使用jdk proxy --> 
 <property name="optimize" value="true" /> 
 <!-- 事务属性, 顺序: PROPAGATION, ISOLATION, readOnly, -Exceptions, +Exceptions --> 
 <property name="transactionAttributes"> 
  <props> 
   <prop key="insert*">PROPAGATION_REQUIRED</prop> 
   <prop key="update*">PROPAGATION_REQUIRED</prop> 
   <prop key="delete*">PROPAGATION_REQUIRED</prop> 
   <prop key="list">PROPAGATION_REQUIRED, readOnly</prop> 
   <prop key="search*">PROPAGATION_REQUIRED, readOnly</prop> 
  </props> 
 </property> 
</bean> 
<bean id="companyDao" class="dao.hibernate.CompanyDaoImpl">
 <property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>
<!-- 需要被增强的bean通常命名为xxxxTarget -->
<bean id="companyServiceTarget" class="services.CompanyService">
 <property name="companyDao" ref="companyDao" />
</bean>
<!-- 事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref="dataSource" />
</bean>
<!-- 被代理之后的service,它具有事务功能,程序中我们就使用它 -->
<bean id="companyService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
 <!-- 事务管理器 -->
 <property name="transactionManager" ref="txManager" />
 <!-- 需要被代理的目标 -->
 <property name="target" ref="companyServiceTarget" />
 <!-- optimize可选,true代表使用CGLib, false代表使用jdk proxy -->
 <property name="optimize" value="true" />
 <!-- 事务属性, 顺序: PROPAGATION, ISOLATION, readOnly, -Exceptions, +Exceptions -->
 <property name="transactionAttributes">
  <props>
   <prop key="insert*">PROPAGATION_REQUIRED</prop>
   <prop key="update*">PROPAGATION_REQUIRED</prop>
   <prop key="delete*">PROPAGATION_REQUIRED</prop>
   <prop key="list">PROPAGATION_REQUIRED, readOnly</prop>
   <prop key="search*">PROPAGATION_REQUIRED, readOnly</prop>
  </props>
 </property>
</bean>
测试:
view plaincopy to clipboardprint?
public class Test {  
 public static void main(String[] args) throws InterruptedException, SQLException{  
  ApplicationContext c = new ClassPathXmlApplicationContext("spring-test.xml");  
  CompanyService s = (CompanyService)c.getBean("companyService");  
  List list = s.list();  
  System.out.println(list.size());  
  s.insertCompany(new Company("www.ddd.com","ddd","wuhan", new Date()));  
}} 
public class Test {
 public static void main(String[] args) throws InterruptedException, SQLException{
  ApplicationContext c = new ClassPathXmlApplicationContext("spring-test.xml");
  CompanyService s = (CompanyService)c.getBean("companyService");
  List list = s.list();
  System.out.println(list.size());
  s.insertCompany(new Company("www.ddd.com","ddd","wuhan", new Date()));
}}
 

你会发现,这里的配置和前面讲的spring aop多么的相同,不错,他们的原理都是一样的,如果你没有了解过spring aop, 建议看一下。

通常情况下,service层需要的事务控制的配置大都相同,而且方法名大都是insertXXX, updateXXX, deleteXXX, searchXXX, checkXXX诸如此类,所以我们可以配置一个可复用的事务代理:

spring事务管理第二种配置方式:目标bean共享代理基类
view plaincopy to clipboardprint?
<!-- abstract="true"标明它是抽象的 --> 
<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> 
 <property name="transactionManager" ref="txManager" /> 
 <!-- target被注释掉 --> 
 <!--property name="target" ref="companyServiceTarget" /--> 
 <property name="transactionAttributes">   
  <props> 
   <prop key="insert*">PROPAGATION_REQUIRED</prop> 
   <prop key="update*">PROPAGATION_REQUIRED</prop> 
   <prop key="delete*">PROPAGATION_REQUIRED</prop> 
   <prop key="list">PROPAGATION_REQUIRED, readOnly</prop> 
   <prop key="search*">PROPAGATION_REQUIRED, readOnly</prop> 
  </props> 
 </property> 
</bean> 
<bean id="companyService" parent="baseTransactionProxy"> 
 <property name="target" ref="companyServiceTarget" /> 
</bean> 
<bean id="otherService" parent="baseTransactionProxy"> 
 <property name="target" ref="otherServiceTarget" /> 
</bean> 
...... 
<!-- abstract="true"标明它是抽象的 -->
<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
 <property name="transactionManager" ref="txManager" />
 <!-- target被注释掉 -->
 <!--property name="target" ref="companyServiceTarget" /-->
 <property name="transactionAttributes">
  <props>
   <prop key="insert*">PROPAGATION_REQUIRED</prop>
   <prop key="update*">PROPAGATION_REQUIRED</prop>
   <prop key="delete*">PROPAGATION_REQUIRED</prop>
   <prop key="list">PROPAGATION_REQUIRED, readOnly</prop>
   <prop key="search*">PROPAGATION_REQUIRED, readOnly</prop>
  </props>
 </property>
</bean>
<bean id="companyService" parent="baseTransactionProxy">
 <property name="target" ref="companyServiceTarget" />
</bean>
<bean id="otherService" parent="baseTransactionProxy">
 <property name="target" ref="otherServiceTarget" />
</bean>
......

虽然我们为需要事务增强的bean配置了代理类,但是难保用户还会直接使用目标对象companyServiceTarget; 可以使用拦截器.

spring事务管理第三种配置方式:使用拦截器

view plaincopy to clipboardprint?
<!-- 配置一个事务拦截器,他对目标对象有事务增强的作用 --> 
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> 
    <property name="transactionManager" ref="txManager" /> 
    <property name="transactionAttributes">    
        <props>    
            <prop key="*">PROPAGATION_REQUIRED</prop>    
        </props>    
    </property>    
</bean> 
<!-- 为目标对象自动创建代理 --> 
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">    
    <property name="beanNames"> 
        <list>    
            <value>companyServiceTarget</value> 
        </list>    
    </property>    
    <property name="interceptorNames">    
        <list>    
            <value>transactionInterceptor</value>    
        </list>    
    </property>    
</bean> 
<!-- 配置一个事务拦截器,他对目标对象有事务增强的作用 -->
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
 <property name="transactionManager" ref="txManager" />
    <property name="transactionAttributes"> 
        <props> 
            <prop key="*">PROPAGATION_REQUIRED</prop> 
        </props> 
    </property> 
</bean>
<!-- 为目标对象自动创建代理 -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
    <property name="beanNames">
        <list> 
            <value>companyServiceTarget</value>
        </list> 
    </property> 
    <property name="interceptorNames"> 
        <list> 
            <value>transactionInterceptor</value> 
        </list> 
    </property> 
</bean>

测试:此时可以直接使用companyServiceTarget.

view plaincopy to clipboardprint?
public class Test {  
    public static void main(String[] args) throws InterruptedException, SQLException{  
        ApplicationContext c = new ClassPathXmlApplicationContext("spring-test.xml");  
        //直接使用目标对象  
        CompanyService s = (CompanyService)c.getBean("companyServiceTarget");  
        List list = s.list();  
        System.out.println(list.size());  
        s.insertCompany(new Company("www.ddd.com","ddd","wuhan", new Date()));  
}} 
public class Test {
 public static void main(String[] args) throws InterruptedException, SQLException{
  ApplicationContext c = new ClassPathXmlApplicationContext("spring-test.xml");
  //直接使用目标对象
  CompanyService s = (CompanyService)c.getBean("companyServiceTarget");
  List list = s.list();
  System.out.println(list.size());
  s.insertCompany(new Company("www.ddd.com","ddd","wuhan", new Date()));
}}

spring事务管理第四种配置方式:使用tx命名空间

view plaincopy to clipboardprint?
<tx:advice id="txAdvice" transaction-manager="txManager"> 
    <tx:attributes> 
        <tx:method name="insert*" propagation="REQUIRED" /> 
        <tx:method name="update*" propagation="REQUIRED" /> 
        <tx:method name="delete*" propagation="REQUIRED" /> 
        <tx:method name="list" propagation="REQUIRED" read-only="true" /> 
    </tx:attributes> 
</tx:advice> 
<aop:config> 
    <aop:pointcut id="interceptorPointCuts" 
        expression="execution(* services.*Service(..))" /> 
    <aop:advisor advice-ref="txAdvice" 
        pointcut-ref="interceptorPointCuts" />          
</aop:config> 
<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="insert*" propagation="REQUIRED" />
        <tx:method name="update*" propagation="REQUIRED" />
        <tx:method name="delete*" propagation="REQUIRED" />
        <tx:method name="list" propagation="REQUIRED" read-only="true" />
    </tx:attributes>
</tx:advice>
<aop:config>
    <aop:pointcut id="interceptorPointCuts"
        expression="execution(* services.*Service(..))" />
    <aop:advisor advice-ref="txAdvice"
        pointcut-ref="interceptorPointCuts" />       
</aop:config>

但是这种配置就需要把tx, aop的命名空间加入进来了:臭长臭长的。

view plaincopy to clipboardprint?
<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"   
        xmlns:context="http://www.springframework.org/schema/context
        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-2.5.xsd  
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd  
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 
......  
</beans> 
<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"
  xmlns:context="http://www.springframework.org/schema/context"
  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-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
......
</beans>

spring事务管理第五种配置方式:注解

略...

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sunxing007/archive/2009/09/22/4579225.aspx

分享到:
评论

相关推荐

    学习笔记:尚硅谷Spring6基础篇

    ### 学习笔记:尚硅谷Spring6基础篇 #### 一、Spring框架概述 ##### 1.1 Spring是什么? Spring是一款主流的Java EE轻量级开源框架,由“Spring之父”Rod Johnson提出并创立。Spring的主要目标是简化Java企业级...

    Spring学习笔记+学习源码.zip

    这份"Spring学习笔记+学习源码.zip"资源包含了深入学习Spring及其相关技术的知识点,以及实践代码,对提升Spring技能将大有裨益。 首先,我们来详细讨论Spring框架的主要组件和功能: 1. **依赖注入(Dependency ...

    Spring学习笔记&源码

    本资料“Spring学习笔记&源码”是基于网易云课堂黑马程序员的Spring四天精通课程,旨在帮助学习者深入理解和实践Spring框架。 笔记部分可能会涵盖以下内容: 1. **Spring概述**:介绍Spring框架的历史、特点和主要...

    Spring学习笔记(精华全记录)

    ### Spring学习笔记(精华全记录) #### Spring框架概述 Spring框架源自Rod Johnson的个人项目,最初于2002年末发布。Spring并非一开始就作为一个完整的框架出现,而是从一个项目逐步发展而来。随着项目的成熟,...

    Spring.NET学习笔记16——事务管理Demo源码

    在本篇“Spring.NET学习笔记16——事务管理Demo源码”中,我们将深入探讨Spring.NET的事务管理机制及其实际应用。 事务管理是软件开发中的关键部分,它确保数据库操作的一致性和完整性。Spring.NET通过其事务管理...

    spring学习笔记

    ### Spring学习笔记知识点详解 #### 一、Spring框架概述 **Spring** 是一个开源的、分层的企业级应用开发框架,旨在简化Java EE应用程序的开发。它的主要目标是提高开发效率,减少耦合度,并提供一种更为简洁的...

    Spring学习笔记.zip

    面向切面编程是Spring提供的另一个重要功能,它允许开发者将关注点分离,比如日志、事务管理等,从主业务逻辑中抽取出来,形成独立的“切面”。切面可以在特定的“连接点”(如方法调用)上织入,提高了代码的复用性...

    Spring学习笔记.doc

    ### Spring学习笔记知识点详解 #### 一、Spring框架概述 **1.1 什么是Spring** Spring框架是一个开源的轻量级应用框架,主要用于简化企业级应用程序的开发过程。它的核心特性在于提供了一种灵活的方式来组织和...

    Spring框架学习笔记

    这份"Spring框架学习笔记"涵盖了Spring框架的基础知识、核心组件以及高级特性,对于初学者来说是一份宝贵的资料。 一、Spring框架概述 Spring框架是为了解决企业应用开发的复杂性而设计的,它提供了一个全面的基础...

    spring学习笔记事务的

    #### 一、Spring事务概述 在Spring框架中,事务管理是一项重要的功能,它能够确保业务操作的一致性和完整性。Spring提供了两种类型的事务管理:编程式事务管理和声明式事务管理。 - **编程式事务管理**:通过代码...

    马士兵老师spring框架学习笔记

    马士兵老师是知名的Java教育专家,他的Spring框架学习笔记深入浅出,对于初学者和进阶者来说都是一份宝贵的资源。这份笔记涵盖了Spring的核心概念、配置、AOP(面向切面编程)、DI(依赖注入)等关键知识点。 1. **...

    spring hibernate 事务管理学习笔记(一)

    在学习过程中,阅读博客如《spring hibernate 事务管理学习笔记(一)》是非常有益的,它通常会包含具体的示例代码和实践建议。你可以参考这个博客链接(https://microjava.iteye.com/blog/525973),结合实际项目,...

    spring hibernate 事务管理学习笔记(二)

    在本篇“Spring Hibernate 事务管理学习笔记(二)”中,我们将深入探讨Spring框架与Hibernate集成时如何实现高效、安全的事务管理。这是一篇关于源码分析和技术工具使用的文章,适合对Java开发和数据库操作有基础...

    Spring学习笔记(18)----使用Spring配置文件实现事务管理

    这篇"Spring学习笔记(18)----使用Spring配置文件实现事务管理"着重讲解如何通过Spring的XML配置来管理应用中的事务。这里我们将深入探讨相关知识点。 首先,Spring提供了两种事务管理方式:编程式事务管理和声明式...

    Spring学习笔记

    ### Spring学习笔记:深入理解AOP与Annotation驱动的动态代理 #### 核心知识点解析: 在探讨Spring框架中AOP(面向切面编程)及基于Annotation的动态代理之前,我们首先需要了解AOP的基本概念及其在Spring中的实现...

    SPRING学习笔记2

    Spring学习笔记2涵盖了Spring框架的核心概念和重要特性,旨在帮助开发者深入理解并熟练掌握Spring的使用。 1. **依赖注入(Dependency Injection, DI)**:这是Spring最核心的设计原则,它允许对象之间的依赖关系在...

    spring学习笔记(十五)-编程式事务例子

    在本篇“Spring学习笔记(十五)——编程式事务例子”中,我们将深入探讨Spring框架中的编程式事务管理。在实际开发中,我们通常使用声明式事务管理,它基于AOP(面向切面编程)来简化事务处理。然而,有时为了更细...

    Spring的学习笔记

    以下将详细介绍Spring学习笔记中的主要知识点。 **面向抽象编程** 面向抽象编程是一种设计原则,强调在代码中使用接口或抽象类,而不是具体实现类。这使得系统更具有灵活性,易于扩展和维护。在Spring框架中,我们...

    spring学习笔记(十六)-声明式事务的例子

    在本篇“spring学习笔记(十六)-声明式事务的例子”中,我们将深入探讨这一主题。 首先,声明式事务管理基于AOP(面向切面编程)实现,Spring通过代理模式在方法调用前后自动插入事务管理的代码。它主要通过两种方式...

    Spring学习笔记.rar

    这份"Spring学习笔记"涵盖了Spring框架的基础到高级应用,对于想要深入理解并掌握Spring的开发者来说是一份宝贵的资料。 1. **Spring概述**:Spring是一个开源的Java平台,主要设计用于简化企业级应用开发。它提供...

Global site tag (gtag.js) - Google Analytics