一、使用编程方式
数据源、事务的底层配置
<?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