Spring配置事务的五种方式

Spring
1:对每一个服务层类Bean配置一个代理:
a.首先创建一个maven quick-start 项目,然后配置依赖包:
mysql-connector,spring-context,spring-orm,hibernate,
hibernate-core,dbcp2(数据源)
b.在test数据库中编写数据库脚本并执行,以及编写applicationContext.xml文件(在src目录下):

DROP TABLE IF EXISTS account;  
CREATE TABLE account (  
accountId int primary key auto_increment,  
accountname varchar(20),  
money int not null  
);  

INSERT INTO ACCOUNT(ACCOUNTNAME,MONEY) VALUES('zhangsan',100);  
INSERT INTO ACCOUNT(ACCOUNTNAME,MONEY) VALUES('lisi',100);  

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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">
  <bean id="dataSource"  
        class="org.apache.commons.dbcp2.BasicDataSource">  
        <property name="driverClassName"  
            value="com.mysql.jdbc.Driver">  
        property>  
        <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT">property>  
        <property name="username" value="root">property>  
        <property name="password" value="mysqladmin">property>  
    bean>  

    <bean id="sessionFactory"  
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
        <property name="dataSource">  
            <ref bean="dataSource" />  
        property>  
        <property name="hibernateProperties">  
            <props>  
                <prop key="hibernate.dialect">  
                    org.hibernate.dialect.MySQLDialect  
                prop>  
                <prop key="hibernate.show_sql">trueprop>  
            props>  
        property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xmlvalue>  
            list>  
        property>  
    bean>  


      
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    bean>

    
    <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO">
     <property name="sessionFactory" ref="sessionFactory" />
    bean>
    <bean id="accountServiceTarget" class="kai.SpringTransaction1.AccountService">
        <property name="accountDAO" ref="accountDAO" />
    bean>
      
    <bean id="accountService"  
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">  
             
           <property name="transactionManager" ref="transactionManager" />     
        <property name="target" ref="accountServiceTarget" />  
         <property name="proxyInterfaces" value="kai.SpringTransaction1.IAccountService" />
          
        <property name="transactionAttributes">  
            <props>  
                <prop key="*">PROPAGATION_REQUIREDprop>
            props>  
        property>  
    bean>  
beans>

c.编写Account类

package kai.SpringTransaction1;

public class Account implements java.io.Serializable {  

    /** 
     *  
     */  
    private static final long serialVersionUID = 909891879728703117L;  

    private Integer accountId;  
    private String accountname;  
    private Integer money;  

    // Property accessors  

    public Integer getAccountId() {  
        return this.accountId;  
    }  

    public void setAccountId(Integer accountId) {  
        this.accountId = accountId;  
    }  

    public String getAccountname() {  
        return this.accountname;  
    }  

    public void setAccountname(String accountname) {  
        this.accountname = accountname;  
    }  

    public Integer getMoney() {  
        return this.money;  
    }  

    public void setMoney(Integer money) {  
        this.money = money;  
    }  

    // Constructors  

    /** default constructor */  
    public Account() {  
    }  

    /** full constructor */  
    public Account(String accountname, Integer money) {  
        this.accountname = accountname;  
        this.money = money;  
    }  

}  

d.编写AccountDAO和IAccountService,AccountService和Account.hbm.xml,因为是基于代理的,因此服务层必须要有接口,即必须有IAccountService,不能直接代理AccountService。

package kai.SpringTransaction1;

import org.hibernate.SessionFactory;
public class AccountDAO  {  
      public SessionFactory sessionFactory;
      public void setSessionFactory(SessionFactory sessionFactory){
          this.sessionFactory=sessionFactory;
      }
    @SuppressWarnings("deprecation")
    public void addMoney(Integer accountId, int money) {  
        Account ac=(Account) sessionFactory.getCurrentSession().get(Account.class, accountId);
        ac.setMoney(money+ac.getMoney());
        sessionFactory.getCurrentSession().update(ac,accountId);
    }  

    public void subMoney(Integer accountId, int money) {  
        Account ac=(Account) sessionFactory.getCurrentSession().get(Account.class, accountId);
        ac.setMoney(ac.getMoney()-money);
        sessionFactory.getCurrentSession().update(ac,accountId); 
    }  
}  

package kai.SpringTransaction1;

public interface IAccountService {
     public void transfer(Integer fromAccountId, Integer toAccountId, int money) ;
}

package kai.SpringTransaction1;


public class AccountService implements IAccountService{   

    private AccountDAO accountDAO;   

    /**  
     * 通过 Spring 将 DAO 注入到 Service  
     *   
     * @param accountDAO  
     * 
     */  
    public void setAccountDAO(AccountDAO accountDAO) {   
        this.accountDAO = accountDAO;   
    }   

    /**  
     * 转账方法包括两个原子方法:转出方法和转入方法  
     *   
     * @param fromAccountId  
     * @param toAccountId  
     * @param money  
     */  
    public void transfer(Integer fromAccountId, Integer toAccountId, int money) {   
        accountDAO.subMoney(fromAccountId, money);   
        accountDAO.addMoney(toAccountId, money);   
    }   
}  

"1.0" encoding="utf-8"?>  
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  
  
    "kai.SpringTransaction1.Account" table="account" catalog="test">  
        "accountId" type="java.lang.Integer">  
            "accountId" />  
            "native" />  
          
        "accountname" type="java.lang.String">  
            "accountname" length="20" />  
          
        "money" type="java.lang.Integer">  
            "money" length="20" />  
          
      
  

e.编写测试类

package kai.SpringTransaction1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
        ApplicationContext act = new FileSystemXmlApplicationContext(   
                "src/applicationContext.xml");   
        IAccountService accountService = (IAccountService) act   
                .getBean("accountService");   
        try {   
            // 帐号1转账1元至帐号2   
            accountService.transfer(1, 2, 1);  
        } catch (Exception e) {   
            System.out.println("转账失败");   
        }   
    }
}

f.运行:查看数据库可知钱成功转账,若将测试类中改为从账户1转到不存在的张户2,则1的钱也不会减少。
2.对服务层所有bean配置同一个代理:
只需将1中的applicationContext.xml文件修改为如下:


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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">
  <bean id="dataSource"  
        class="org.apache.commons.dbcp2.BasicDataSource">  
        <property name="driverClassName"  
            value="com.mysql.jdbc.Driver">  
        property>  
        <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT">property>  
        <property name="username" value="root">property>  
        <property name="password" value="mysqladmin">property>  
    bean>  

    <bean id="sessionFactory"  
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
        <property name="dataSource">  
            <ref bean="dataSource" />  
        property>  
        <property name="hibernateProperties">  
            <props>  
                <prop key="hibernate.dialect">  
                    org.hibernate.dialect.MySQLDialect  
                prop>  
                <prop key="hibernate.show_sql">trueprop>  
            props>  
        property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xmlvalue>  
            list>  
        property>  
    bean>  


      
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    bean>

    
    <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO">
     <property name="sessionFactory" ref="sessionFactory" />
    bean>
    <bean id="accountServiceTarget" class="kai.SpringTransaction1.AccountService">
        <property name="accountDAO" ref="accountDAO" />
    bean>
      
       <bean id="transactionBase"  
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"  
            lazy-init="true" abstract="true">  
          
        <property name="transactionManager" ref="transactionManager" />  
          
        <property name="transactionAttributes">  
            <props>  
                <prop key="*">PROPAGATION_REQUIREDprop>  
            props>  
        property>  
    bean>    
      
    <bean id="accountService" parent="transactionBase">  
        <property name="target" ref="accountServiceTarget" />  
    bean>  
beans>

3.基于拦截器的实现,也是只需要修改applicationContext.xml文件:


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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">
  <bean id="dataSource"  
        class="org.apache.commons.dbcp2.BasicDataSource">  
        <property name="driverClassName"  
            value="com.mysql.jdbc.Driver">  
        property>  
        <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT">property>  
        <property name="username" value="root">property>  
        <property name="password" value="mysqladmin">property>  
    bean>  

    <bean id="sessionFactory"  
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
        <property name="dataSource">  
            <ref bean="dataSource" />  
        property>  
        <property name="hibernateProperties">  
            <props>  
                <prop key="hibernate.dialect">  
                    org.hibernate.dialect.MySQLDialect  
                prop>  
                <prop key="hibernate.show_sql">trueprop>  
            props>  
        property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xmlvalue>  
            list>  
        property>  
    bean>  


      
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    bean>

    
    <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO">
     <property name="sessionFactory" ref="sessionFactory" />
    bean>
    <bean id="accountService" class="kai.SpringTransaction1.AccountService">
        <property name="accountDAO" ref="accountDAO" />
    bean>
       
    <bean id="transactionInterceptor"  
        class="org.springframework.transaction.interceptor.TransactionInterceptor">  
        <property name="transactionManager" ref="transactionManager" />  
          
        <property name="transactionAttributes">  
            <props>  
                <prop key="*">PROPAGATION_REQUIREDprop>  
            props>  
        property>  
    bean>

    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
        <property name="beanNames">  
            <list>  
                <value>*Servicevalue>
            list>  
        property>  
        <property name="interceptorNames">  
            <list>  
                <value>transactionInterceptorvalue>  
            list>  
        property>  
    bean>  
beans>

4.使用AOP方式实现:
在1的基础上修改applicationContext.xml文件以及引入依赖包:aspectj和aspectjweaver。


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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">
  <bean id="dataSource"  
        class="org.apache.commons.dbcp2.BasicDataSource">  
        <property name="driverClassName"  
            value="com.mysql.jdbc.Driver">  
        property>  
        <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT">property>  
        <property name="username" value="root">property>  
        <property name="password" value="mysqladmin">property>  
    bean>  

    <bean id="sessionFactory"  
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
        <property name="dataSource">  
            <ref bean="dataSource" />  
        property>  
        <property name="hibernateProperties">  
            <props>  
                <prop key="hibernate.dialect">  
                    org.hibernate.dialect.MySQLDialect  
                prop>  
                <prop key="hibernate.show_sql">trueprop>  
            props>  
        property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xmlvalue>  
            list>  
        property>  
    bean>  


      
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    bean>

    
    <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO">
     <property name="sessionFactory" ref="sessionFactory" />
    bean>
    <bean id="accountService" class="kai.SpringTransaction1.AccountService">
        <property name="accountDAO" ref="accountDAO" />
    bean>
        
    <tx:advice id="TestAdvice" transaction-manager="transactionManager">  
          
        <tx:attributes>  
            <tx:method name="save*" propagation="REQUIRED" />  
            <tx:method name="del*" propagation="REQUIRED" />  
            <tx:method name="update*" propagation="REQUIRED" />  
            <tx:method name="add*" propagation="REQUIRED" />  
            <tx:method name="*" propagation="REQUIRED" />  
        tx:attributes>  
    tx:advice>  
    <aop:config>  
          
        <aop:pointcut id="services"  
            expression="execution(* kai.SpringTransaction1.AccountService.*(..))" />  
        <aop:advisor pointcut-ref="services" advice-ref="TestAdvice" />  
    aop:config>  
beans>

5.注解式事务:(这是我觉得最优雅的):
修改applicationContext.xml文件同时在需要加事务控制的方法上加上@Transactional注解。此处即在AccountService的transfer方法上加上@Transactional注解。


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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">
  <bean id="dataSource"  
        class="org.apache.commons.dbcp2.BasicDataSource">  
        <property name="driverClassName"  
            value="com.mysql.jdbc.Driver">  
        property>  
        <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT">property>  
        <property name="username" value="root">property>  
        <property name="password" value="mysqladmin">property>  
    bean>  

    <bean id="sessionFactory"  
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
        <property name="dataSource">  
            <ref bean="dataSource" />  
        property>  
        <property name="hibernateProperties">  
            <props>  
                <prop key="hibernate.dialect">  
                    org.hibernate.dialect.MySQLDialect  
                prop>  
                <prop key="hibernate.show_sql">trueprop>  
            props>  
        property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xmlvalue>  
            list>  
        property>  
    bean>  


      
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    bean>

    
    <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO">
     <property name="sessionFactory" ref="sessionFactory" />
    bean>
    <bean id="accountService" class="kai.SpringTransaction1.AccountService">
        <property name="accountDAO" ref="accountDAO" />
    bean>
        
 <tx:annotation-driven transaction-manager="transactionManager"/>
beans>

补充说明:
1.@Transactional
(1)这个注解放在类上面,会对这个类中的所有public方法都起作用;
(2)放在方法上,只有当这个方法是public方法才起作用。
(3)事务的传播性:@Transactional(propagation=Propagation.REQUIRED)
(4)事务的隔离级别:@Transactional(isolation = Isolation.READ_UNCOMMITTED)
参考文章:
http://blog.csdn.net/it_man/article/details/5074371
http://blog.csdn.net/lifangshui/article/details/6324348
http://blog.csdn.net/qh_java/article/details/51811533

你可能感兴趣的:(spring)