JDBCTemplate和HibernateTemplate事物源码解析

JDBCTemplate和HibernateTemplate事物源码解析 博客分类: spring

由于项目中对批量的sql进行入库处理。所以打算用jdbcTemplate。在其他的增删改查中都是用hibernateTemplate

在这里考虑到一个问题,就是当jdbcTemplatehibernateTemplate结合用的时候,事物是怎么样的了?

经过测试:在一个方法中同时使用jdbcTemplate,和hibernateTemplate对数据进行增加操作。然后抛出异常。

发现事物是可以正常回滚的。但为什么可以这样了?看了下源码终于了解了一些。

<bean id="oaTM" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref bean="oaSessionFactory"/></property>
</bean>

总而言之。不管是使用jdbcTemplate或者是hibernateTemplate都是对jdbc的封装,说白了,对数据库的操作还是

使用connection,在回滚事物的时候还是调用了connection. Rollback方法来进行回滚的。

这一回想,在hibernate中有个sessionFactory. getCurrentSession()方法。调用的当前的线程session

意思就是用当前的connection来操作数据。

spring管理中有这么一个类来进行当前线程的数据绑定:TransactionSynchronizationManager

public abstract class TransactionSynchronizationManager

/* */ {

/* 77 */ private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);

/* */

/* 80 */ private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal("Transactional resources");

/* */

/* 83 */ private static final ThreadLocal<List<TransactionSynchronization>> synchronizations = new NamedThreadLocal("Transaction synchronizations");

/* */

/* 86 */ private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal("Current transaction name");

/* */

/* 89 */ private static final ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal("Current transaction read-only status");

/* */

/* 92 */ private static final ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal("Current transaction isolation level");

/* */

/* 95 */ private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal("Actual transaction active");

OpenEntityManagerInViewFilterOpenSessionInViewInterceptor等需要获取当前线程对象的类中都用到了此类。

在使用hibernateTemplate可以使用hibernateTemplate.sessionFactory.getCurrentSession().connection获取当前的connection对象

在使用jdbcTemplate获取当前的connection对象的方法是:

public abstract class DataSourceUtils {

public static Connection doGetConnection(DataSource dataSource) throws SQLException {

Assert.notNull(dataSource, "No DataSource specified");

//①首先尝试从事务同步管理器中获取数据连接

ConnectionHolder conHolder =

(ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);

if (conHolder != null && (conHolder.hasConnection() ||

conHolder.isSynchronizedWithTransaction())) {

conHolder.requested();

if (!conHolder.hasConnection()) {

logger.debug("Fetching resumed JDBC Connection from DataSource");

conHolder.setConnection(dataSource.getConnection());

}

return conHolder.getConnection();

}

//②如果获取不到连接,则直接从数据源中获取连接

Connection con = dataSource.getConnection();

//③如果拥有事务上下文,则将连接绑定到事务上下文中

if (TransactionSynchronizationManager.isSynchronizationActive()) {

ConnectionHolder holderToUse = conHolder;

if (holderToUse == null) {

holderToUse = new ConnectionHolder(con);

}

else {holderToUse.setConnection(con);}

holderToUse.requested();

TransactionSynchronizationManager.registerSynchronization(

new ConnectionSynchronization(holderToUse, dataSource));

holderToUse.setSynchronizedWithTransaction(true);

if (holderToUse != conHolder) {

TransactionSynchronizationManager.bindResource(

dataSource, holderToUse);

}

}

return con;

}

}

当在同在方法中打印出这两个种方法获取的connection对象是同一对象时,基本上证明了在使用jdbcTemplatehibernateTemplate的时候。

在事物的完整性方面来说是没有问题的。下面我们在看看org.springframework.orm.hibernate3.HibernateTransactionManager。

.HibernateTransactionManager 的父类是PlatformTransactionManager

.HibernateTransactionManager有很多子类,实现了事物的管理:

CciLocalTransactionManage.

DataSourceTransactionManage.

HibernateTransactionManage.

JdoTransactionManage.

JpaTransactionManage.

public abstract interface PlatformTransactionManager

{

//事物状态

public abstract TransactionStatus getTransaction(TransactionDefinition paramTransactionDefinition)

throws TransactionException;

//提交

public abstract void commit(TransactionStatus paramTransactionStatus)

throws TransactionException;

//回滚

public abstract void rollback(TransactionStatus paramTransactionStatus)

throws TransactionException;

}

/* */ public class HibernateTransactionManager extends AbstractPlatformTransactionManager

/* */ implements ResourceTransactionManager, BeanFactoryAware, InitializingBean

/* */ {

在这些事物管理实现类中都使用了 TransactionSynchronizationManager.bindResource(key);来获取当前绑定的对象;如SessionHolder

/* */ protected Object doGetTransaction()

/* */ {

/* 430 */ HibernateTransactionObject txObject = new HibernateTransactionObject(null);

/* 431 */ txObject.setSavepointAllowed(isNestedTransactionAllowed());

/* */

/* 433 */ SessionHolder sessionHolder =

/* 434 */ (SessionHolder)TransactionSynchronizationManager.getResource(getSessionFactory());

/* 435 */ if (sessionHolder != null) {

/* 436 */ if (this.logger.isDebugEnabled()) {

/* 437 */ this.logger.debug("Found thread-bound Session [" +

/* 438 */ SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction");

/* */ }

/* 440 */ txObject.setSessionHolder(sessionHolder);

/* */ }

/* 442 */ else if (this.hibernateManagedSession) {

/* */ try {

/* 444 */ Session session = getSessionFactory().getCurrentSession();

/* 445 */ if (this.logger.isDebugEnabled()) {

/* 446 */ this.logger.debug("Found Hibernate-managed Session [" +

/* 447 */ SessionFactoryUtils.toString(session) + "] for Spring-managed transaction");

/* */ }

/* 449 */ txObject.setExistingSession(session);

/* */ }

/* */ catch (HibernateException ex) {

/* 452 */ throw new DataAccessResourceFailureException(

/* 453 */ "Could not obtain Hibernate-managed Session for Spring-managed transaction", ex);

/* */ }

/* */ }

/* */

/* 457 */ if (getDataSource() != null) {

/* 458 */ ConnectionHolder conHolder = (ConnectionHolder)

/* 459 */ TransactionSynchronizationManager.getResource(getDataSource());

/* 460 */ txObject.setConnectionHolder(conHolder);

/* */ }

/* */

/* 463 */ return txObject;

/* */ }

Aop的事物管理中:通过拦截器来对相应的事物进行处理。

在对Spring AOP源码分析中关于AOP代理如何起作用时,我们知道SpringAOP代理通过invoke回调方法对切入点方法进行拦截处理,这个invoke方法是AOP联盟的方法拦截器MethodInterceptor接口中定义的方法,用于对AOP代理对象的方法进行包装处理。事务拦截器TransactionInterceptor正是通过这个invoke拦截方法实现事务的拦截处理,源码如下:

/* */ public class TransactionInterceptor extends TransactionAspectSupport

/* */ implements MethodInterceptor, Serializable

1. //事务拦截器的拦截方法

2. public Object invoke(final MethodInvocation invocation) throws Throwable {

3. //通过AOP获取事务的目标类

4. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

5. //通过事务属性源TransactionAttributeSource读取事务的属性配置,即调用上面名称匹配

6. //事务属性源NameMatchTransactionAttributeSource的方法

7. final TransactionAttribute txAttr =

8. getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);

9. //获取Spring事务管理IoC容器配置的事务处理器

10. final PlatformTransactionManager tm = determineTransactionManager(txAttr);

11. //获取目标类指定方法的事务连接点

12. final String joinpointIdentification = methodIdentification(invocation.getMethod(), targetClass);

13. //区分不同类型的PlatformTransactionManager事务处理器,不同类型的事务处理器调用//方式不同。对CallbackPreferringPlatformTransactionManager,需要回调函数来//实现事务的创建和提交,对非CallbackPreferringPlatformTransactionManager来//说,则不需要使用回调函数来实现事务处理。

14. //非CallbackPreferringPlatformTransactionManager类型的事务处理器

15. if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {

16. //创建事务,将当前事务状态和信息保存到TransactionInfo对象中

17. TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

18. Object retVal = null;

19. try {

20. //沿着拦截器链调用处理,使得最后目标对象的方法得到调用

21. retVal = invocation.proceed();

22. }

23. catch (Throwable ex) {

24. //在调用拦截器拦过程中出现异常,则根据事务配置进行提交或回滚处理

25. completeTransactionAfterThrowing(txInfo, ex);

26. throw ex;

27. }

28. //清除与当前线程绑定的事务信息

29. finally {

30. cleanupTransactionInfo(txInfo);

31. }

32. //通过事务处理器来对事务进行提交

33. commitTransactionAfterReturning(txInfo);

34. return retVal;

35. }

36. //CallbackPreferringPlatformTransactionManager类型的事务处理器

37. else {

38. //通过回调函数对事务进行处理

39. try {

40. //执行实现TransactionCallback接口的doInTransaction回调方法

41. Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,

42. new TransactionCallback<Object>() {

43. //实现TransactionCallback接口匿名内部类的回调方法

44. public Object doInTransaction(TransactionStatus status) {

45. //创建和准备事务

46. TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);

47. try {

48. //沿着拦截器拦调用

49. return invocation.proceed();

50. }

51. //拦截器链处理过程中产生异常

52. catch (Throwable ex) {

53. //如果事务对异常进行回滚处理

54. if (txAttr.rollbackOn(ex)) {

55. //如果异常时运行时异常,则事务回滚处理

56. if (ex instanceof RuntimeException) {

57. throw (RuntimeException) ex;

58. }

59. //如果不是运行时异常,则提交处理

60. else {

61. throw new ThrowableHolderException(ex);

62. }

63. }

64. //如果事务对异常不进行回滚处理

65. else {

66. //提交处理

67. return new ThrowableHolder(ex);

68. }

69. }

70. //清除当前线程绑定的事务信息

71. finally {

72. cleanupTransactionInfo(txInfo);

73. }

74. }

75. });

76. //对调用结果异常进行处理。

77. //如果是ThrowableHolder类型的异常,则转换为Throwable抛出

78. if (result instanceof ThrowableHolder) {

79. throw ((ThrowableHolder) result).getThrowable();

80. }

81. //如果不是ThrowableHolder类型的异常,则异常不做处理直接抛出

82. else {

83. return result;

84. }

85. }

86. catch (ThrowableHolderException ex) {

87. throw ex.getCause();

88. }

89. }

90. }

completeTransactionAfterThrowing()是事物回滚方法。调用的是父类的方法。

/* */ public abstract class TransactionAspectSupport

/* */ implements BeanFactoryAware, InitializingBean

/* */ {

protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex)

/* */ {

/* 404 */ if ((txInfo != null) && (txInfo.hasTransaction())) {

/* 405 */ if (this.logger.isTraceEnabled()) {

/* 406 */ this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +

/* 407 */ "] after exception: " + ex);

/* */ }

/* 409 */ if (txInfo.transactionAttribute.rollbackOn(ex)) {

/* */ try {

//这里调用的是: AbstractPlatformTransactionManagerrollback方法。最终调用的相应的子类的doRollback方法。

// 比如用的是hibernateTranactionManager就是调用其中的doRollback方法。

// txObject.getSessionHolder().getTransaction().rollback();这里最终调用的还是HibernateTransactionRollback方法

//归根揭底,都是调用了connection.rollback().DataSoucreTransactionManager也类似。

/* 411 */ txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());

/* */ }

/* */ catch (TransactionSystemException ex2) {

/* 414 */ this.logger.error("Application exception overridden by rollback exception", ex);

/* 415 */ ex2.initApplicationException(ex);

/* 416 */ throw ex2;

/* */ }

/* */ catch (RuntimeException ex2) {

/* 419 */ this.logger.error("Application exception overridden by rollback exception", ex);

/* 420 */ throw ex2;

/* */ }

/* */ catch (Error err) {

/* 423 */ this.logger.error("Application exception overridden by rollback error", ex);

/* 424 */ throw err;

/* */ }

/* */ }

转载于:https://my.oschina.net/xiaominmin/blog/1598178

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值