Spring 對事務管理的支持

一、Spring對事務管理的支持

    Spring爲事務管理提供了一致的編程模板,在高層次創建了統一的事務抽象。也就是說,無論選擇Spring JDBC、Hibernate 、JPA 仍是iBatis,Spring都讓咱們能夠用統一的編程模型進行事務管理。java

    在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)Hibernatespring

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"/>

 

二、編程式事務管理
    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;
    }    
}

 

三、使用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實現類:sql

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:express

<?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進行聲明式事務配置:apache

<?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>

測試方法:session

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........");
    }
}
 
四、使用註解配置聲明式事務
    使用@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:使事務註解生效app

<?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>
相關文章
相關標籤/搜索