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);  
<?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: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&amp;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">true</prop>  
            </props>  
        </property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xml</value>  
            </list>  
        </property>  
    </bean>  


    <!-- 定义事务管理器(声明式的事务) -->  
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- 配置DAO和service -->
    <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配置一个代理 -->
    <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_REQUIRED</prop>
            </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);   
    }   
}  

<?xml version="1.0" encoding="utf-8"?>  
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
<!--  
    Mapping file autogenerated by MyEclipse Persistence Tools 
-->  
<hibernate-mapping>  
    <class name="kai.SpringTransaction1.Account" table="account" catalog="test">  
        <id name="accountId" type="java.lang.Integer">  
            <column name="accountId" />  
            <generator class="native" />  
        </id>  
        <property name="accountname" type="java.lang.String">  
            <column name="accountname" length="20" />  
        </property>  
        <property name="money" type="java.lang.Integer">  
            <column name="money" length="20" />  
        </property>  
    </class>  
</hibernate-mapping>  

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文件修改为如下:

<?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: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&amp;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">true</prop>  
            </props>  
        </property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xml</value>  
            </list>  
        </property>  
    </bean>  


    <!-- 定义事务管理器(声明式的事务) -->  
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- 配置DAO和service -->
    <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的共同代理-->  
       <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_REQUIRED</prop>  
            </props>  
        </property>  
    </bean>    
      <!-- 所有bean配置一个代理 -->
    <bean id="accountService" parent="transactionBase">  
        <property name="target" ref="accountServiceTarget" />  
    </bean>  
</beans>

3.基于拦截器的实现,也是只需要修改applicationContext.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: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&amp;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">true</prop>  
            </props>  
        </property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xml</value>  
            </list>  
        </property>  
    </bean>  


    <!-- 定义事务管理器(声明式的事务) -->  
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- 配置DAO和service -->
    <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_REQUIRED</prop>  
            </props>  
        </property>  
    </bean>

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

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

<?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: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&amp;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">true</prop>  
            </props>  
        </property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xml</value>  
            </list>  
        </property>  
    </bean>  


    <!-- 定义事务管理器(声明式的事务) -->  
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- 配置DAO和service -->
    <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>
      <!-- 下面使用aop切面的方式来实现 事务控制-->  
    <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注解。

<?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: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&amp;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">true</prop>  
            </props>  
        </property>  
        <property name="mappingResources">  
            <list>  
                <value>kai/SpringTransaction1/Account.hbm.xml</value>  
            </list>  
        </property>  
    </bean>  


    <!-- 定义事务管理器(声明式的事务) -->  
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- 配置DAO和service -->
    <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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值