前言:
近期在做项目的时候,发现有很多bug是因为spring的事务问题引起。究其原因主要是项目组人员对事务的掌握程度不一导致。接下来试着写几篇博客站在我理解的角度上将这些问题解释清楚。
编程式事务管理:
简单来说,编程式事务管理是需要我们在代码中手动的开启事务,关闭事务,提交,回滚更加的细粒度。对应方法有beginTransaction()、commit()、rollback()、closeTransaction()等一系列方法。
以上针对的是jdbc没有被任何框架封装的操作。这些基础的增删改查,相信我们在初学数据库操作都做过。类似代码如下:
/** * 开始事务 * @param cnn */ public static void beginTransaction(Connection cnn){ if(cnn!=null){ try { if(cnn.getAutoCommit()){ cnn.setAutoCommit(false); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }/** * 提交事务 * @param cnn */ public static void commitTransaction(Connection cnn){ if(cnn!=null){ try { if(!cnn.getAutoCommit()){ cnn.commit(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 回滚事务 * @param cnn */ public static void rollBackTransaction(Connection cnn){ if(cnn!=null){ try { if(!cnn.getAutoCommit()){ cnn.rollback(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
这种方式,我们利用了原生的jdbc方法。但是我们如果调用spring封装的底层api方法,则需要配置一番。
public class BankServiceImpl implements BankService { private BankDao bankDao; private TransactionDefinition txDefinition; private PlatformTransactionManager txManager; ...... public boolean transfer(Long fromId, Long toId, double amount) { TransactionStatus txStatus = txManager.getTransaction(txDefinition); boolean result = false; try { result = bankDao.transfer(fromId, toId, amount); txManager.commit(txStatus); } catch (Exception e) { result = false; txManager.rollback(txStatus); System.out.println("Transfer Error!"); } return result; }
}
<bean id="bankService" class="footmark.spring.core.tx.programmatic.origin.BankServiceImpl"> <property name="bankDao" ref="bankDao"/> <property name="txManager" ref="transactionManager"/> <property name="txDefinition"> <bean class="org.springframework.transaction.support.DefaultTransactionDefinition"> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/> </bean> </property> </bean>
申明式事务管理:
主要通过spring的aop的方式,通过注解,或者配置文件。对方法前后加上事务控制,是属于粗粒度的。示例如下
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans><bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation"> <value>classpath:sqlmap-config.xml</value> </property> <property name="dataSource" ref="dataSource" /> </bean> <!-- feng.tan --> <bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate"> <property name="sqlMapClient"> <ref bean="sqlMapClient" /> </property> </bean> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <property name="transactionAttributes"> <props> <prop key="remove*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="modify*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <!-- 自动代理 --> <bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*Service</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean>
</beans>
上面的xml是我实际项目中的配置文件。采用自动代理的方式给service层的方法符合条件的加上了事务控制。
参考资料:http://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/section4.html
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于