spring 3.x 实现事务的几种方式

一、使用编程方式

数据源、事务的底层配置

<?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: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/tx     
    http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
      
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">  
        <property name="driver" value="com.mysql.jdbc.Driver" />  
        <property name="driverUrl" value="jdbc:mysql://localhost:3306/test" />  
        <property name="user" value="username" />  
        <property name="password" value="userpwd" /> 
    </bean>  
      
    <!-- jdbc事务管理器 -->  
    <bean id="transactionManager"  
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
        <property name="dataSource">  
            <ref local="dataSource" />  
        </property>  
    </bean>  
    <!--事务模板 -->  
    <bean id="transactionTemplate"  
        class="org.springframework.transaction.support.TransactionTemplate">  
        <property name="transactionManager">  
            <ref local="transactionManager" />  
        </property>  
        <!--ISOLATION_DEFAULT 表示由使用的数据库决定  -->  
        <property name="isolationLevelName" value="ISOLATION_DEFAULT"/>  
        <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>  
        <!-- <property name="timeout" value="30"/> -->  
    </bean> 
</beans> 


DAO层的配置

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
    <property name="dataSource" ref="dataSource"/>  
</bean>    
<bean id="merchantMapDAO" class="cn.com.nantian.epayment.dao.MerchantMapDAO">  
    <property name="jdbcTemplate" ref="jdbcTemplate"/>  
</bean>  
<bean id="payOrderDAO" class="cn.com.nantian.epayment.dao.PayOrderDAO">  
    <property name="jdbcTemplate" ref="jdbcTemplate"/>  
</bean> 


SERVICE层的配置

<bean id="elecChnlFrontPayService"  
    class="cn.com.nantian.epayment.pay.service.ElecChnlFrontPayServiceImpl">  
    <property name="merchantMapDAO" ref="merchantMapDAO" />  
    <property name="payOrderDAO" ref="payOrderDAO" />  
    <property name="transactionTemplate" ref="transactionTemplate" />  
</bean>


程序示例代码

private PayOrderDAO payOrderDAO;  
  
protected TransactionTemplate transactionTemplate;  
  
/** 
 * 保存支付订单 
 */  
protected PayOrder savePayReq(final PayOrder payOrder) {  
  
    PayOrder order = (PayOrder) this.transactionTemplate.execute(new TransactionCallback() {  
                @Override  
                public Object doInTransaction(TransactionStatus status) {  
                    // 查看是否已经存在支付订单,如果已经存在则返回订单主键   
                    PayOrder payOrderTemp = payOrderDAO.findOrder(String.valueOf(payOrder.getPayOrderId()));  
  
                    // 由支付渠道类型(PayChannelType)转换得到交易类型(PayType)   
                    if (payOrder.getPayChannelId().equalsIgnoreCase(PAY_CHNL_ACT_BAL)) {// 账户余额支付   
                        payOrder.setPayType("3");  
                    } else if (payOrder.getPayChannelId().equalsIgnoreCase(PAY_CHNL_FAST_PAY)) {// 联通快捷支付   
                        payOrder.setPayType("4");  
                    } else {// 网银网关支付   
                        payOrder.setPayType("2");  
                    }  
  
                    // 比对新的支付金额与原订单金额是否一致,如不一致则提示错误   
                    if (payOrderTemp == null) {  
                        String orderId = payOrderDAO.save(payOrder);  
                        payOrder.setPayOrderId(orderId);  
                        return payOrder;  
                    } else {  
                        return payOrderTemp;  
                    }  
                }  
            });  
    if ("2".equals(order.getOrderState())) {// 2:表示支付成功   
        throw new EpaymentBizException(StatusCode.DQSystem.PAY_FAIL, "同一订单不能重复支付");  
    } else if (payOrder.getPayAmt().longValue() != order.getPayAmt().longValue()) {  
        throw new EpaymentBizException(StatusCode.DQSystem.PAY_FAIL, "交易金额与原订单不一致");  
    } else {  
        return payOrder;  
    }    
}  
  
public PayOrderDAO getPayOrderDAO() {  
    return payOrderDAO;  
}  
  
public void setPayOrderDAO(PayOrderDAO payOrderDAO) {  
    this.payOrderDAO = payOrderDAO;  
}  
  
public TransactionTemplate getTransactionTemplate() {  
    return transactionTemplate;  
}  
  
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {  
    this.transactionTemplate = transactionTemplate;  
}


 

二、使用XML配置

Spring的数据源设置

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >  
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  <property name="url" value="jdbc:mysql://localhost:3306/test"/>  
  <property name="username" value="root"/>  
  <property name="password" value="123456"/>  
</bean>


Spring对iBATIS的支持,Spring对ibatis主要提供org.springframework.orm.ibatis.SqlMapClientFactoryBean类来进行支持

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">  
  <property name="dataSource" ref="dataSource"/>  
  <property name="configLocation" value="/config/sqlMapConfig.xml"/>  
</bean>  


Spring对iBATIS DAO的支持,Spring提供org.springframework.orm.ibatis.support.SqlMapClientDaoSupport来对iBATIS DAO进行支持,通过调用该类的getSqlMapClientTemplate()方法来获得对iBATIS的控制访问

<bean id="accountDao" class="com.hj.dao.AccountDaoImp"> 
   <property name="sqlMapClient" ref="sqlMapClient"/> 
</bean>
<bean id="bankService" class="com.hj.bankOps.DefaultBankService">
  <property name="accountDao" ref="bankAccountDao"/>  
</bean>

这里DefaultBankService类主要实现BankService接口(提供服务的方法定义),其内部引用一个BankAccountDao实例来对数据库进行访问。BankAccountDao类主要继承SqlMapClientDaoSupport。

 

Spring 配置事务

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
     <property name="dataSource" ref="dataSource"/>  
</bean>


配置事务通知

<tx:advice id="transactionManagerAdivice" transaction-manager="transactionManager">  
   <tx:attributes>
      <tx:method name="create*"  isolation="READ_COMMITTED" propagation="REQUIRED" rollback-for="java.lang.RuntionException" />  
      <tx:method name="del*"  isolation="READ_COMMITTED" propagation="REQUIRED" rollback-for="java.lang.RuntionException" /> 
      <tx:method name="*"  propagation="REQUIRED" read-only="true" />  
   </tx:attributes>  
</tx:advice>


配置切入点和方面

<aop:config>  
   <aop:pointcut expression="execution(* com.hj.bankOps.DefaultBankService.*(..))" id="bankServicePc"/>  
   <aop:advisor advice-ref="transactionManagerAdivice" pointcut-ref="bankServicePc"/>    
</aop:config>

上述execution(* com.hj.bankOps.DefaultBankService.*(..))表达式表示切入点为该类中的任何方法。所以当DefaultBankService类中方法调用时就会进行事务管理,并且当抛出RuntimeException时,自动进行回滚操作
此处一定要注意包名和类名的大小写~~


遇到的问题:在<Spring高级程序设计>一书上,对AOP XML事务配置时,其通知部分并没有设置具体属性(缺少 rollback-for="java.lang.RuntionException")

<tx:attributes>  
      <tx:method name="*"  isolation="READ_COMMITTED"  propagation="REQUIRED"/>  
</tx:attributes>

这样的写法在DefaultBankService方法调用中如果有异常抛出,事务并不进行相应回滚操作

 

三、使用注释配置

Spring的数据源设置

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >  
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  <property name="url" value="jdbc:mysql://localhost:3306/test"/>  
  <property name="username" value="root"/>  
  <property name="password" value="123456"/>  
</bean>


Spring对iBATIS DAO的支持

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">  
  <property name="dataSource" ref="dataSource"/>  
  <property name="configLocation" value="/config/sqlMapConfig.xml"/>  
</bean>
<bean id="accountDao" class="com.hj.dao.AccountDaoImp">
  <property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
<bean id="bankService" class="com.hj.bankOps.DefaultBankService">
  <property name="accountDao" ref="bankAccountDao"/>  
</bean>


对业务类进行事务的标注,例如:@Transactional

public class OrderMainManagerImpl extends BaseManager implements OrderMainManager {
    ……
}


Spring 配置事务

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
     <property name="dataSource" ref="dataSource"/>  
</bean>
<!-- 对标注@Transactional注释的bean进行加工处理,以织入事务管理切面 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

需要引入:xmlns:tx=http://www.springframework.org/schema/tx
                    xsi:schemaLocation=" http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"

 

完成,可以去测试了

参考:spring 3.x 企业应用开发实战
            http://jackandroid.iteye.com/blog/614620

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值