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