zoukankan      html  css  js  c++  java
  • 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>
     
     
  • 相关阅读:
    C#MessageBox使用
    ListBox的使用
    中文乱码的几种情况以及解决方法
    使用Application
    Android笔记之标题栏的各种操作
    Android笔记之日期选择器
    Viewpager制作自动左右循环滑动
    JAVA入门到精通-第17讲-排序
    ***JAVA入门到精通-第14讲-final-作业评讲
    JAVA入门到精通-第13讲-抽象类-接口
  • 原文地址:https://www.cnblogs.com/yangyquin/p/5583158.html
Copyright © 2011-2022 走看看