Spring 编程式事务管理

来源:互联网 发布:网易邮箱大师mac版 编辑:程序博客网 时间:2024/05/19 05:03
 

编程式和声明式事务的区别

      Spring提供了对编程式事务和声明式事务的支持,编程式事务允许用户在代码中精确定义事务的边界,而声明式事务(基于AOP)有助于用户将操作与事务规则进行解耦。 
      简单地说,编程式事务侵入到了业务代码里面,但是提供了更加详细的事务管理;而声明式事务由于基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现。

如何实现编程式事务?

Spring提供两种方式的编程式事务管理,分别是使用TransactionTemplate和直接使用PlatformTransactionManager。

# 使用TransactionTemplate

      采用TransactionTemplate和采用其他Spring模板,如JdbcTempalte和HibernateTemplate是一样的方法。它使用回调方法,把应用程序从处理取得和释放资源中解脱出来。如同其他模板,TransactionTemplate是线程安全的。

 使用案例代码如下:

  #数据模型层

package com.sunline.entity;/** * Account entity. @author MyEclipse Persistence Tools */public class Account  implements java.io.Serializable {    // Fields         private Integer id;     private String name;     private Double money;    // Constructors    /** default constructor */    public Account() {    }/** minimal constructor */    public Account(String name) {        this.name = name;    }        /** full constructor */    public Account(String name, Double money) {        this.name = name;        this.money = money;    }       // Property accessors    public Integer getId() {        return this.id;    }        public void setId(Integer id) {        this.id = id;    }    public String getName() {        return this.name;    }        public void setName(String name) {        this.name = name;    }    public Double getMoney() {        return this.money;    }        public void setMoney(Double money) {        this.money = 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="com.sunline.entity.Account" table="account" catalog="association">        <id name="id" type="java.lang.Integer">            <column name="id" />            <generator class="native"></generator>        </id>        <property name="name" type="java.lang.String">            <column name="name" length="20" not-null="true" />        </property>        <property name="money" type="java.lang.Double">            <column name="money" precision="10" />        </property>    </class></hibernate-mapping>

#配置文件

  applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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"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/context                         http://www.springframework.org/schema/context/spring-context-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">    <!-- 引用外部文件 db.properties读取数据库配置-->    <context:property-placeholder location="classpath:db.properties"/>    <!-- schemaLocation后面两个命名空间是扫描该包必须有的 -->    <!-- 扫描com.sunline包以及所有子包,为所有加了注解的类创建bean -->    <context:component-scan base-package="com.sunline">    </context:component-scan><bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName"value="${driverClassName}"></property><property name="url"value="${url}"></property><property name="username" value="${username}"></property><property name="password" value="${password}"></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="dialect">    org.hibernate.dialect.MySQLDialect</prop>                <prop key="hibernate.hbm2ddl.auto">true</prop>                <prop key="hibernate.show_sql">true</prop> </props></property><property name="mappingResources"><list><value>com/sunline/entity/Account.hbm.xml</value></list></property>   </bean>      <!-- 配置Hibernate事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">        <property name="sessionFactory" ref="sessionFactory" />    </bean>   <!-- ==================================1.编程式的事务管理=============================================== --><!-- 配置事务管理的模板:Spring为了简化事务管理的代码而提供的类 --><bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="transactionManager"/></bean></beans>

#数据访问层

AccountDao.java

package com.sunline.dao;import javax.annotation.Resource;import org.hibernate.SessionFactory;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import org.springframework.stereotype.Repository;@Repository(value="accountDao")public class AccountDao extends HibernateDaoSupport {/* * 使用注解必须添加以下方式 */    @Resource      public void setSessionFacotry(SessionFactory sessionFacotry) {          super.setSessionFactory(sessionFacotry);      }      /* *  @param out :转出账号 *  @param money :转账金额 */public void outMoney(String out, double money){String hsql ="update Account set money = money-? where name = ?";System.out.println("成功转出金额!");this.getHibernateTemplate().bulkUpdate(hsql, new Object[]{money,out});}/* * @param in:转入账号 * @param money:转账金额 */public void inMoney(String in, Double money) {String hsql = "update Account set money = money+? where name = ?";System.out.println("成功转入金额!");this.getHibernateTemplate().bulkUpdate(hsql, new Object[]{money,in});}}
#业务逻辑层

AccountBiz1.java

package com.sunline.biz;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Service;import org.springframework.transaction.TransactionStatus;import org.springframework.transaction.support.TransactionCallbackWithoutResult;import org.springframework.transaction.support.TransactionTemplate;import com.sunline.dao.AccountDao;@Service(value="accountBizOne")public class AccountBiz1 {//注入事务管理的模板@Autowired@Qualifier("transactionTemplate") TransactionTemplate transactionTemplate;/* * 转账 */@Autowired@Qualifier("accountDao")            //使用@Qualifier注解来说明使用哪一个实现类    AccountDao accountDao;/** * @param out:转出账号 * @param in:转入账号 * @param money:转账金额 */public void transfer(final String out, final String in, final Double money) {/* * 第一种:没有事务管理,一方转账成功,一方因为程序异常收不到钱 *///accountDao1.outMoney(out, money);//int i = 1/0;//accountDao1.inMoney(in, money);/* * 第二种添加编程式事务管理 */transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus arg0) {// TODO Auto-generated method stubaccountDao.outMoney(out, money);int i = 1/0;                           //模拟程序出现异常accountDao.inMoney(in, money);}});}}
#测试类

package com.sunline.test;import javax.annotation.Resource;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.Configuration;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.sunline.biz.AccountBiz1;//@Configuration("classpath:applicationContext1.xml")public class Testone {public static void main(String[] args) {// TODO Auto-generated method stub    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");        AccountBiz1 accountBiz1 = (AccountBiz1) ctx.getBean("accountBizOne");accountBiz1.transfer("海哥", "杨旭", 200d);}}





原创粉丝点击