`
ccii
  • 浏览: 56137 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Spring的事务管理

阅读更多
一、概述
  Spring的事务管理不需要与任何特定的事务API耦合,声明式事务基于Spring AOP实现。JavaEE应用的传统事务有两种策略:全局事务和局部事务,全局事务由应用服务器管理,需要底层服务器的JTA(java事务API)支持,局部事务和底层所采用的持久化技术有关,当采用JDBC持久化技术时,需要使用Connection对象来操作事务,而采用Hibernate持久化技术时,需要使用Session对象来操作事务。
  Spring事务策略是通过PlatformTransactionManager接口实现,该接口是Spring事务策略的核心。它有许多不同的实现类,应用程序面向与平台无关的接口编程,当底层采用不同的持久层技术时,系统只需使用不同的PlatformTransactionManager实现类即可---而这种切换通常由Spring容器负责管理,应用程序既无需与具体的API耦合,也无须与特定实现类耦合,从而将应用和持久化技术、事务API彻底分离开来。故Spring的事务管理机制是一种典型的策略模式。Spring完全支持像事务跨多个数据库资源这种跨多个事务性资源的全局事务。

二、使用TransactionProxyFactoryBean创建事务代理(Spring1.x)
2.1 DAO接口
package test.dao;
public interface NewsDao{
    public void insert(String title, String content);
}

2.2 DAO实现
package test.dao.impl;
import javax.sql.DataSource;
import java.sql.Connection;
import org.springframework.jdbc.core.JdbcTemplate;
import org.crazyit.app.dao.*;
public class NewsDaoImpl implements NewsDao{
    private DataSource ds;
    public void setDs(DataSource ds){
        this.ds = ds;
    }
    public void insert(String title, String content){
        JdbcTemplate jt = new JdbcTemplate(ds);
        jt.update("insert into news_inf values(null , ? , ?)", title , content);
        //两次插入的数据违反唯一键约束
        jt.update("insert into news_inf values(null , ? , ?)", title , content);
        //如果增加事务控制,我们发现第一条记录也插不进去。
        //如果没有事务控制,则第一条记录可以被插入
    }
}

2.3 Spring配置文件 bean.xml
<?xml version="1.0" encoding="GBK"?>
<!-- Spring配置文件的根元素,使用spring-beans-3.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <!-- 定义数据源Bean,使用C3P0数据源实现 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <!-- 指定连接数据库的驱动 -->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <!-- 指定连接数据库的URL -->
        <property name="jdbcUrl" value="jdbc:mysql://localhost/javaee"/>
        <!-- 指定连接数据库的用户名 -->
        <property name="user" value="root"/>
        <!-- 指定连接数据库的密码 -->
        <property name="password" value="32147"/>
        <!-- 指定连接数据库连接池的最大连接数 -->
        <property name="maxPoolSize" value="40"/>
        <!-- 指定连接数据库连接池的最小连接数 -->
        <property name="minPoolSize" value="1"/>
        <!-- 指定连接数据库连接池的初始化连接数 -->
        <property name="initialPoolSize" value="1"/>
        <!-- 指定连接数据库连接池的连接的最大空闲时间 -->
        <property name="maxIdleTime" value="20"/>
    </bean>
    <!-- 配置JDBC数据源的局部事务管理器,使用DataSourceTransactionManager 类 -->
    <!-- 该类实现PlatformTransactionManager接口,是针对采用数据源连接的特定实现-->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 配置DataSourceTransactionManager时需要依注入DataSource的引用 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 配置一个业务逻辑Bean -->
    <bean id="newsDao" class="org.crazyit.app.dao.impl.NewsDaoImpl">
        <property name="ds" ref="dataSource"/>
    </bean>
    <!-- 为业务逻辑Bean配置事务代理 -->
    <bean id="newsDaoTrans" class=
    "org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <!-- 为事务代理工厂Bean注入事务管理器 -->
        <property name="transactionManager" ref="transactionManager"/>
        <property name="target" ref="newsDao"/>
        <!-- 指定事务属性 -->
        <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
</beans>

2.4 测试
package test;
import org.springframework.context.support.*;
import org.springframework.context.*;
import org.crazyit.app.dao.*;
public class SpringTest{
    public static void main(String[] args){
        //创建Spring容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
        //获取事务代理Bean
        NewsDao dao = (NewsDao)ctx.getBean("newsDaoTrans" , NewsDao.class);
        //执行插入操作
        dao.insert("疯狂Java" , "轻量级Java EE企业应用实战");
    }
}

三、Spring2.x提供了tx命名空间来配置事务管理
3.1 DAO接口
package org.crazyit.app.dao;
public interface NewsDao{
    public void insert(String title, String content);
}

3.2 DAO实现
package org.crazyit.app.dao.impl;
import javax.sql.DataSource;
import java.sql.Connection;
import org.springframework.jdbc.core.JdbcTemplate;
import org.crazyit.app.dao.*;
public class NewsDaoImpl implements NewsDao{
    private DataSource ds;
    public void setDs(DataSource ds){
        this.ds = ds;
    }
    public void insert(String title, String content){
        JdbcTemplate jt = new JdbcTemplate(ds);
        jt.update("insert into news_inf values(null , ? , ?)", title , content);
        //两次插入的数据违反唯一键约束
        jt.update("insert into news_inf values(null , ? , ?)", title , content);
        //如果增加事务控制,我们发现第一条记录也插不进去。
        //如果没有事务控制,则第一条记录可以被插入
    }
}

3.3 Spring配置文件
<?xml version="1.0" encoding="GBK"?>
<!-- Spring配置文件的根元素,使用spring-beans-3.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    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-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <!-- 定义数据源Bean,使用C3P0数据源实现 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <!-- 指定连接数据库的驱动 -->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <!-- 指定连接数据库的URL -->
        <property name="jdbcUrl" value="jdbc:mysql://localhost/javaee"/>
        <!-- 指定连接数据库的用户名 -->
        <property name="user" value="root"/>
        <!-- 指定连接数据库的密码 -->
        <property name="password" value="32147"/>
        <!-- 指定连接数据库连接池的最大连接数 -->
        <property name="maxPoolSize" value="40"/>
        <!-- 指定连接数据库连接池的最小连接数 -->
        <property name="minPoolSize" value="1"/>
        <!-- 指定连接数据库连接池的初始化连接数 -->
        <property name="initialPoolSize" value="1"/>
        <!-- 指定连接数据库连接池的连接的最大空闲时间 -->
        <property name="maxIdleTime" value="20"/>
    </bean>
    <!-- 配置JDBC数据源的局部事务管理器,使用DataSourceTransactionManager 类 -->
    <!-- 该类实现PlatformTransactionManager接口,是针对采用数据源连接的特定实现-->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 配置DataSourceTransactionManager时需要依注入DataSource的引用 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 配置一个业务逻辑Bean -->
    <bean id="newsDao" class="org.crazyit.app.dao.impl.NewsDaoImpl">
        <property name="ds" ref="dataSource"/>
    </bean>
    <!-- 配置事务增强处理,指定事务管理器 -->
    <tx:advice id="txAdvice"
        transaction-manager="transactionManager">
        <!-- 用于配置详细的事务语义 -->
        <tx:attributes>
            <!-- 所有以'get'开头的方法是read-only的 -->
            <tx:method name="get*" read-only="true"/>
            <!-- 其他方法使用默认的事务设置 -->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
    <!-- AOP配置的元素 -->
    <aop:config>
        <!-- 配置一个切入点,匹配org.crazyit.app.dao.impl包下
            所有以Impl结尾的类里、所有方法的执行 -->
        <aop:pointcut id="myPointcut"
            expression="execution(* org.crazyit.app.dao.impl.*Impl.*(..))"/>
            <!-- 指定在txAdvice切入点应用txAdvice事务增强处理 -->
        <aop:advisor advice-ref="txAdvice"
            pointcut-ref="myPointcut"/>
    </aop:config>
</beans>

3.4 测试
package lee;
import org.springframework.context.support.*;
import org.springframework.context.*;
import org.crazyit.app.dao.*;
public class SpringTest{
    public static void main(String[] args){
        //创建Spring容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
        //获取事务代理Bean
        NewsDao dao = (NewsDao)ctx.getBean("newsDao" , NewsDao.class);
        //执行插入操作
        dao.insert("疯狂Java" , "轻量级Java EE企业应用实战");
    }
}

四、使用@Transactional Annotation
4.1 DAO接口
package org.crazyit.app.dao;
public interface NewsDao{
    public void insert(String title, String content);
}

4.2 DAO实现
package org.crazyit.app.dao.impl;
import javax.sql.DataSource;
import java.sql.Connection;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.*;
import org.crazyit.app.dao.*;
public class NewsDaoImpl implements NewsDao{
    private DataSource ds;
    public void setDs(DataSource ds){
        this.ds = ds;
    }
    @Transactional(propagation=Propagation.REQUIRED)
    public void insert(String title, String content){
        JdbcTemplate jt = new JdbcTemplate(ds);
        jt.update("insert into news_inf values(null , ? , ?)", title , content);
        //两次插入的数据违反唯一键约束
        jt.update("insert into news_inf values(null , ? , ?)", title , content);
        //如果增加事务控制,我们发现第一条记录也插不进去。
        //如果没有事务控制,则第一条记录可以被插入
    }
}

4.3 Spring配置文件bean.xml
<?xml version="1.0" encoding="GBK"?>
<!-- Spring配置文件的根元素,使用spring-beans-3.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    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-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <!-- 定义数据源Bean,使用C3P0数据源实现 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <!-- 指定连接数据库的驱动 -->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <!-- 指定连接数据库的URL -->
        <property name="jdbcUrl" value="jdbc:mysql://localhost/javaee"/>
        <!-- 指定连接数据库的用户名 -->
        <property name="user" value="root"/>
        <!-- 指定连接数据库的密码 -->
        <property name="password" value="32147"/>
        <!-- 指定连接数据库连接池的最大连接数 -->
        <property name="maxPoolSize" value="40"/>
        <!-- 指定连接数据库连接池的最小连接数 -->
        <property name="minPoolSize" value="1"/>
        <!-- 指定连接数据库连接池的初始化连接数 -->
        <property name="initialPoolSize" value="1"/>
        <!-- 指定连接数据库连接池的连接的最大空闲时间 -->
        <property name="maxIdleTime" value="20"/>
    </bean>
    <!-- 配置一个业务逻辑Bean -->
    <bean id="newsDao" class="org.crazyit.app.dao.impl.NewsDaoImpl">
        <property name="ds" ref="dataSource"/>
    </bean>
    <!-- 配置JDBC数据源的局部事务管理器,使用DataSourceTransactionManager 类 -->
    <!-- 该类实现PlatformTransactionManager接口,是针对采用数据源连接的特定实现-->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 配置DataSourceTransactionManager时需要依注入DataSource的引用 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 根据Annotation来生成事务代理 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

4.4 测试
package lee;
import org.springframework.context.support.*;
import org.springframework.context.*;
import org.crazyit.app.dao.*;
public class SpringTest{
    public static void main(String[] args){
        //创建Spring容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
        //获取事务代理Bean
        NewsDao dao = (NewsDao)ctx.getBean("newsDao" , NewsDao.class);
        //执行插入操作
        dao.insert("疯狂Java" , "轻量级Java EE企业应用实战");
    }
}
分享到:
评论

相关推荐

    Spring事务管理Demo

    Spring事务管理的目的是确保数据的一致性和完整性,尤其是在多操作、多资源的环境中。本Demo将深入探讨Spring如何实现事务的管理。 首先,Spring提供了两种主要的事务管理方式:编程式事务管理和声明式事务管理。 ...

    spring事务管理

    ### Spring事务管理详解 #### 一、事务管理基础概念 在深入探讨Spring事务管理之前,我们需要先理解什么是事务。事务可以被定义为一系列的操作集合,这些操作作为一个整体被提交或回滚。简单来说,事务就是一个不...

    Spring事务管理开发必备jar包

    本资源包提供了进行Spring事务管理开发所需的所有关键库,包括框架基础、核心组件、AOP(面向切面编程)支持、日志处理、编译工具以及与数据库交互的相关jar包。下面将对这些知识点进行详细解释: 1. **Spring框架*...

    spring 事务管理的理解

    Spring 框架是Java开发中...理解并熟练掌握Spring事务管理,对于提升应用程序的稳定性和可靠性至关重要。在实际开发中,结合声明式事务管理、事务传播行为、隔离级别和回滚规则,可以有效地确保数据的完整性和一致性。

    Spring事务管理.pdf

    Spring事务管理.pdf 1.资料 2.本地事务与分布式事务 3.编程式模型 4.宣告式模型

    Synchronized锁在Spring事务管理下线程不安全

    Synchronized锁在Spring事务管理下,导致线程不安全。

    Spring事务管理的jar包

    本篇将深入探讨Spring事务管理的核心概念、工作原理以及如何使用`spring-tx-3.2.0.RELEASE.jar`这个jar包。 首先,我们需要理解什么是事务。在数据库系统中,事务是一组操作,这些操作被视为一个整体,要么全部完成...

    Spring事务管理失效原因汇总

    标题“Spring事务管理失效原因汇总”指出了本文的核心内容是分析在使用Spring框架进行事务管理时可能遇到的问题及其原因。描述部分进一步说明了事务失效的后果往往不明显,容易在测试环节被忽略,但在生产环境中出现...

    spring事务管理5种方法

    本篇文章将深入探讨Spring事务管理的五种方法,旨在帮助开发者更好地理解和运用这一核心特性。 首先,我们来了解什么是事务。在数据库操作中,事务是一组逻辑操作,这些操作要么全部成功,要么全部失败,确保数据的...

    Spring事务管理4种方式

    本文将详细介绍Spring事务管理的四种方式:编程式事务管理、声明式事务管理、PlatformTransactionManager接口以及TransactionTemplate。 1. **编程式事务管理**:这是一种手动控制事务的方式,通过在代码中调用`...

    详细介绍Spring事务管理

    ### Spring事务管理详解 #### 一、Spring事务管理的重要性及必要性 在现代软件开发中,事务管理是一项至关重要的技术,特别是在涉及数据库操作时。事务能够确保一系列操作要么全部成功,要么全部失败,这对于保持...

    spring事务管理.rar

    Spring事务管理是Spring框架的核心特性之一,它提供了一种强大且灵活的方式来管理应用程序中的事务边界。在企业级Java应用中,事务处理是确保数据一致性、完整性和可靠性的关键部分。本篇文章将深入探讨Spring的事务...

    spring事务管理.doc

    总的来说,Spring事务管理提供了一种灵活、强大的方式来处理应用程序中的事务,无论是在简单还是复杂的事务场景下,都能有效保证数据的一致性和完整性。通过声明式事务管理,开发者可以将关注点从事务细节中解脱出来...

    Spring事务管理

    Spring事务管理是Spring框架的核心特性之一,它提供了一种在Java应用中管理和协调数据库事务的标准方式。对于有Java基础的开发者来说,理解并掌握Spring事务管理至关重要,因为这有助于确保数据的一致性和完整性,...

    Spring事务管理配置文件问题排查

    当出现像描述中那样的问题——SQL语句执行出错但事务未回滚时,我们需要深入理解Spring事务管理的配置和机制。以下是一些关键知识点: 1. **Spring事务管理类型**: - **编程式事务管理**:通过`...

    spring事务管理几种方式代码实例

    spring事务管理几种方式代码实例:涉及编程式事务,声明式事务之拦截器代理方式、AOP切面通知方式、AspectJ注解方式,通过不同方式实例代码展现,总结spring事务管理的一般规律,从宏观上加深理解spring事务管理特性...

    Spring事务管理和SpringJDBC思维导图

    在思维导图"Spring Transaction.twd"中,可能包含了Spring事务管理的各个概念和它们之间的关系,如事务的ACID属性(原子性、一致性、隔离性和持久性),事务管理器,以及声明式和编程式事务管理的实现方式。...

    Spring事务管理的方法

    ### Spring事务管理的方法 #### 一、引言 在企业级应用开发中,事务管理是一项至关重要的技术。Spring框架作为Java领域中一个非常流行的轻量级框架,为开发者提供了多种方式来实现事务管理,其中主要分为编程式...

Global site tag (gtag.js) - Google Analytics