Spring 对事务管理的支持

1、Spring对事务管理的支持

Spring为事务管理提供了一致的编程模板,在高层次建立了统一的事务抽象。也就是说,不管选择Spring JDBC、Hibernate 、JPA 还是iBatis,Spring都让我们可以用统一的编程模型进行事务管理。

在Spring事务管理SPI(Service Provider Interface)的抽象层主要包括3个接口,分别是PlatformTransactionManager、TransactionDefinition和TransactionStatus。TransactionDefinition用于描述事务的隔离级别、超时时间、是否为只读事务和事务传播规则等控制事务具体行为的事务属性,这些事务属性可以通过XML配置或注解描述提供,也可以通过手工编程的方式设置。PlatformTransactionManager根据TransactionDefinition提供的事务属性配置信息,创建事务,并用TransactionStatus描述这个激活事务的状态。

1)Spring JDBC 和iBatis

基于数据源的数据管理器

<context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close"
          p:driverClassName="${jdbc.driverClassName}"
          p:url="${jdbc.url}"
          p:username="${jdbc.username}"
          p:password="${jdbc.password}"/>
     <bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
      p:dataSource-ref="dataSource"/>

2)JPA

JAP事务管理器配置

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
          p:dataSource-ref="dataSource"/>
    ...
<bean id="transactionManger" class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFacotry-ref="entityManagerFactory"/>

3)Hibernate

Hibernate3.0事务管理器配置

<bean id="sessionFactory"
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
     p:dataSource-ref="dataSource"
     p:mappingResources="classpath:bbtForum.hbm.xml">

   <property name="hibernateProperties">
     <props>
       <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
       <prop key="hibernate.show_sql">true</prop>
       <prop key="hibernate.generate_statistics">true</prop>
     </props>
   </property>
</bean>

4)JTA

JTA事务管理器

<jee:jndi-lookup id="accountDs" jndi-name="java:comp/env/jdbc/account"/>
<jee:jndi-lookup id="orderDs" jndi-name="java:comp/env/jdbc/account"/>
<bean id="transactionManager"
     class="org.springframework.transaction.jta.JtaTransactionManager"/>

2、编程式事务管理

Spring事务管理提供了模板类org.springframework.transaction.support.TransactionTemplate,以满足一些特殊场合的需要。

package com.baobaotao.service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.baobaotao.dao.ForumDao;
import com.baobaotao.domain.Forum;
public class ForumService1 {
    private ForumDao forumDao;
    //通过IoC注入
    private TransactionTemplate template;
    public void addForum(final Forum forum) {
        template.execute(new TransactionCallbackWithoutResult() {
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                //需要在事务环境中执行的代码
                forumDao.addForum(forum);
            }
        });
    }
    public void setForumDao(ForumDao forumDao) {
        this.forumDao = forumDao;
    }
    public void setTemplate(TransactionTemplate template) {
        this.template = template;
    }
}

3、使用XML配置声明式事务

Spring的声明式事务管理是通过Spring AOP实现的,通过事务的声明性信息,Spring负责将事务管理增强逻辑动态织入到业务方法相应连接点中。这些逻辑包括获取线程绑定资源、开始事务、提交/回滚事务、进行异常转换和处理等工作。

BbtForum接口:

package com.yyq.service;
import com.yyq.domain.Forum;
import com.yyq.domain.Topic;
public interface BbtForum {
    void addTopic(Topic topic) throws Exception;
    void updateForum(Forum forum);
    Forum getForum(int forumId);
    int getForumNum();
}

BbtForumImpl实现类:

package com.yyq.service.impl;
import com.yyq.dao.ForumDao;
import com.yyq.dao.PostDao;
import com.yyq.dao.TopicDao;
import com.yyq.domain.Forum;
import com.yyq.domain.Topic;
import com.yyq.service.BbtForum;

public class BbtForumImpl implements BbtForum {
    private ForumDao forumDao;
    private TopicDao topicDao;
    private PostDao postDao;
    public void addTopic(Topic topic) throws Exception {
        topicDao.addTopic(topic);
//        if(true) throw new PessimisticLockingFailureException("fail");
        postDao.addPost(topic.getPost());
    }
    public Forum getForum(int forumId) {
        return forumDao.getForum(forumId);
    }
    public void updateForum(Forum forum) {
        forumDao.updateForum(forum);
    }
    public int getForumNum() {
        return forumDao.getForumNum();
    }
    public void setForumDao(ForumDao forumDao) {
        this.forumDao = forumDao;
    }
    public void setPostDao(PostDao postDao) {
        this.postDao = postDao;
    }
    public void setTopicDao(TopicDao topicDao) {
        this.topicDao = topicDao;
    }
}

Dao和Datasource配置文件applicationContext-dao.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close"
          p:driverClassName="${jdbc.driverClassName}"
          p:url="${jdbc.url}"
          p:username="${jdbc.username}"
          p:password="${jdbc.password}"/>
    <bean id="jdbcTemplate"
            class="org.springframework.jdbc.core.JdbcTemplate"
            p:dataSource-ref="dataSource"/>

    <bean id="abstracDao" abstract="true" p:jdbcTemplate-ref="jdbcTemplate"/>
    <bean id="forumDao" parent="abstracDao" class="com.yyq.dao.jdbc.ForumDaoImpl" />
    <bean id="postDao" parent="abstracDao" class="com.yyq.dao.jdbc.PostDaoImpl"/>
    <bean id="topicDao" parent="abstracDao" class="com.yyq.dao.jdbc.TopicDaoImpl"/>

</beans>

1)使用原始的TransactionProxyFactoryBean进行声明式事务配置:

<?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-3.0.xsd">
    <!--导入Dao和DataSource的配置文件-->
    <import resource="applicationContext-dao.xml"/>

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--需要实施事务增强的目标业务Bean-->
    <bean id="bbtForumTarget" class="com.yyq.service.impl.BbtForumImpl"
          p:forumDao-ref="forumDao"
          p:topicDao-ref="topicDao"
          p:postDao-ref="postDao"/>
    <!--使用事务代理工程类为目标业务Bean提供事务增强-->
    <bean id="bbtForum" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
          p:transactionManager-ref="txManager"
          p:target-ref="bbtForumTarget">
        <property name="transactionAttributes">
            <props>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
</beans>

测试方法:

import com.yyq.domain.Post;
import com.yyq.domain.Topic;
import com.yyq.service.BbtForum;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestBbtForumPfb {
    public static void main(String[] args) throws Throwable{
        String configPath = "classpath:applicationContext-pfb.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
        BbtForum bbtForum = ctx.getBean("bbtForum",BbtForum.class);
        System.out.println("begin........");
        Topic topic = new Topic();
        topic.setTopicTitle("Title -pfb");
        Post post = new Post();
        post.setPostText("post content -pfb");
        topic.setPost(post);
        bbtForum.addTopic(topic);
        System.out.println("end........");
    }
}

2)基于tx/aop命名空间的配置:

<?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"
       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">
    <!--导入Dao和DataSource的配置文件-->
    <import resource="classpath:applicationContext-dao.xml"/>
    <!--声明事务管理器-->
    <bean id="txManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
          p:dataSource-ref="dataSource"/>
    <!--不再需要为了事务AOP增强的实施而改名换姓-->
    <bean id="bbtForum"
          class="com.yyq.service.impl.BbtForumImpl"
          p:forumDao-ref="forumDao"
          p:topicDao-ref="topicDao"
          p:postDao-ref="postDao"/>
    <!--使用强大的切点表达式语言轻松定义目标方法-->
    <aop:config>
        <!--通过aop定义事务增强切面-->
        <aop:pointcut id="serviceMethod" expression="execution(* com.yyq.service.*Forum.*(..))"/>
        <!--引用事务增强-->
        <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice"/>
    </aop:config>
    <!--事务增强-->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <!--事务属性定义-->
            <tx:method name="get*" read-only="false"/>
            <tx:method name="add*" rollback-for="PessimisticLockingFailureException"/>
            <tx:method name="update*"/>
        </tx:attributes>
    </tx:advice>
</beans>

测试方法:

import com.yyq.domain.Post;
import com.yyq.domain.Topic;
import com.yyq.service.BbtForum;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestBbtForumTx {
    public static void main(String[] args) throws Throwable{
        String configPath = "classpath:applicationContext-tx.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
        BbtForum bbtForum = ctx.getBean(BbtForum.class);

        System.out.println("begin........");
        Topic topic = new Topic();
        topic.setTopicTitle("Title Tx-");
        Post post = new Post();
        post.setPostText("post content -Tx");
        topic.setPost(post);
        bbtForum.addTopic(topic);
        System.out.println("end........");
    }
}

4、使用注解配置声明式事务

使用@Transaction注解声明事务,可以应用于接口定义和接口方法、类定义和类的public方法上。

使用@Transaction注解的业务类:

@Transactional
public class BbtForumImpl implements BbtForum {
    private ForumDao forumDao;
    private TopicDao topicDao;
    private PostDao postDao;
    public void addTopic(Topic topic) throws Exception {
        topicDao.addTopic(topic);
        //if(true) throw new PessimisticLockingFailureException("fail");
        postDao.addPost(topic.getPost());
    }
    public Forum getForum(int forumId) {
        return forumDao.getForum(forumId);
    }
    public void updateForum(Forum forum) {
        forumDao.updateForum(forum);
    }
   ....

applicationContext-anno.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"
       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">
    <import resource="classpath:applicationContext-dao.xml"/>
    <!--由于该Bean实现类标注了@Transaction,所以将会被注解驱动自动织入事务-->
    <bean id="bbtForum"
          class="com.yyq.service.impl.BbtForumImpl"
          p:forumDao-ref="forumDao"
          p:topicDao-ref="topicDao"
          p:postDao-ref="postDao"/>
    <bean id="txManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
          p:dataSource-ref="dataSource"/>
    <!--对标注@Transaction注解的Bean进行加工处理,以织入事务管理切面-->
    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>
</beans>
时间: 2024-10-15 01:13:09

Spring 对事务管理的支持的相关文章

Spring的事务管理

事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 持久性:一旦结束,数据就永久的保存到数据库 如果不考虑隔离性 脏读:一个事务读到另一个事务未提交数据 不可重复读:一个事务读到另一个事务已经提交数据(update)导致一个事务多次查询结果不一致 虚读:一个事务读到另一个事务已经提交数据(insert)导致一个事务多次查询结果不一致 事务的隔离级别

spring笔记--事务管理之声明式事务

事务简介: 事务管理是企业级应用开发中必不可少的技术,主要用来确保数据的完整性和一致性, 事务:就是一系列动作,它们被当作一个独立的工作单元,这些动作要么全部完成,要么全部不起作用. Spring中使用事务: 作为一个受欢迎的企业应用框架,Spring在不同的事务管理API上定义了一个抽象层,而开发时不必了解底层的事务管理API,就可以使用Spring的事务管理机制. Spring既支持编程式的事务管理,也支持声明式的事务管理,大多数情况我们选择后者. 编程式事务管理:将事务管理代码嵌入到业务代

Spring高级事务管理难点剖析

1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(加入已有事务) 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中.这是最常见也是默认的方式. PROPAGATION_SUPPORTS(跟随环境) 支持当前事务,如果当前没有事务,就以非事务方式执行. PROPAGATION_MANDATORY(需要事务) 使用当前的事务,如果当前没有事务,就抛出异

spring,mybatis事务管理配置与@Transactional注解使用

spring,mybatis事务管理配置与@Transactional注解使用[转] 概述事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性.Spring Framework对事务管理提供了一致的抽象,其特点如下: 为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects) 支持声明式事务管理,特别是基

spring,mybatis事务管理配置与@Transactional注解使用[转]

spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性.Spring Framework对事务管理提供了一致的抽象,其特点如下: 为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence A

CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)

JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction management),为不同的事务实现提供了一致的编程模型,这节以JDBC事务为例,介绍Spring的事务管理. 5.3.1  Spring对事务的支持 事务是一组原子(Atomic)操作的工作单元,以数据库存取的实例来说,就是一组SQL指令,这一组SQL指令必须全部执行成功,若因为某个原因未全部执行

Mybatis整合Spring实现事务管理的源码分析

一:前言 没有完整看完,但是看到了一些关键的地方,这里做个记录,过程会有点乱,以后逐渐补充最终归档为完整流程:相信看过框架源码的都知道过程中无法完全确定是怎样的流程,毕竟不可能全部都去测试一遍 ,但是看的过程中灵感的显现很重要(就是直觉知道接下来的步骤是什么应该是什么之类的,但是这个自觉是猜的而非蒙的,即过程里是有往会递推看到了一些关键点的而不是抛色子来确定是哪个子类) ,因此自己写的时候也无法将看的过程里产生的想法写得很细,过程也有点跳,如果大家有疑问最好自己去验证(方式就是搜索然后看哪里调用

Spring框架事务管理机制

一.事务的基本原理Spring事务 的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:    获取连接 Connection con = DriverManager.getConnection()    开启事务con.setAutoCommit(true/false);    执行CRUD    提交事务/回滚事务 con.commit() / con.rollback();    关闭连接

spring与事务管理

就我接触到的事务,使用最多的事务管理器是JDBC事务管理器.现在就记录下在spring中是如何使用JDBC事务管理器 1)在spring中配置事务管理器 <!-- JDBC事务 -->    <bean id="jdbcTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property