读书人

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

发布时间: 2012-12-29 10:28:09 作者: rapoo

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

读书人网 >Web前端

热点推荐