`
m635674608
  • 浏览: 5077168 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

JDBCTemplate和HibernateTemplate事物源码解析

 
阅读更多

由于项目中对批量的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;

/* */ }

/* */ }

0
3
分享到:
评论
3 楼 shmily2038 2012-11-02  
m635674608 写道
shmily2038 写道
在一个方法中同时使用jdbcTemplate,和hibernateTemplate对数据进行增加操作。然后抛出异常。发现事物是可以正常回滚的。 
总结:使用jdbcTemplate和hibernateTemplate拥有一样的统一的事物一致性,可以放心的结合使用。

放心的结合使用不能这样说啊。。如果不牵扯到hibrnate的缓存的话,可以放心使用。如果同时对缓存对象操作的话,hibernate的缓存不能及时更新,会有问题的。

呵呵,也是,不过查询的话,倒是可以放心使用就是。
2 楼 m635674608 2012-11-02  
shmily2038 写道
在一个方法中同时使用jdbcTemplate,和hibernateTemplate对数据进行增加操作。然后抛出异常。发现事物是可以正常回滚的。 
总结:使用jdbcTemplate和hibernateTemplate拥有一样的统一的事物一致性,可以放心的结合使用。

放心的结合使用不能这样说啊。。如果不牵扯到hibrnate的缓存的话,可以放心使用。如果同时对缓存对象操作的话,hibernate的缓存不能及时更新,会有问题的。
1 楼 shmily2038 2012-11-01  
在一个方法中同时使用jdbcTemplate,和hibernateTemplate对数据进行增加操作。然后抛出异常。发现事物是可以正常回滚的。 
总结:使用jdbcTemplate和hibernateTemplate拥有一样的统一的事物一致性,可以放心的结合使用。

相关推荐

    spring jdbcTemplate 源码

    本篇将深入探讨Spring JDBCTemplate的使用及其源码解析,帮助你理解其背后的机制。 首先,让我们了解在不使用JDBCTemplate时,传统的JDBC操作通常涉及以下步骤:加载驱动、建立数据库连接、创建Statement或...

    基于Spring+Spring MVC+JdbcTemplate图书管理系统源码.zip

    Spring框架是目前Java企业级应用开发中最流行的技术之一,它以依赖注入和面向切面编程为特点,使得Java应用开发更加灵活、方便。...它的源码对于初学者理解框架的工作原理和应用开发流程具有很好的参考价值。

    spring源码解析 pdf

    《Spring源码解析》PDF是一份深入探讨Spring框架核心机制的文档,主要涵盖了Spring的IoC容器、JDBC、MVC、AOP、声明式事务处理、与Hibernate的集成以及Acegi(现为Spring Security)框架的鉴权和授权等多个关键模块...

    SpringBoot+JPA+JTA(可选)+JdbcTemplate多数据源配置源码

    本资源包含了两个子项目,分别进行了springboot+jpa+jdbcTemplate的多数据源独立事务配置和jta分布式事务配置,并针对不同的情况编写了事务配置测试接口,还演示了JPA的domain一对多自动生成数据库表且不生成数据库...

    4.Spring中的JdbcTemplate,Spring中的的事务,

    通过本章节的学习,您应该能够掌握如何使用JdbcTemplate进行基本的数据库操作,以及如何在Spring中配置和使用声明式事务来管理复杂的业务流程。这些技能对于开发基于Spring框架的应用程序至关重要。

    Spring持久化模板总结

    Spring提供了多种持久化模板,如JdbcTemplate和HibernateTemplate,以简化数据库操作并减少代码中的样板代码。这两个模板都是Spring JDBC模块的一部分,用于增强对SQL数据库的访问能力。本文将深入探讨Spring对...

    springmvc JdbcTemplate demo

    JdbcTemplate支持多种操作,包括查询、更新、插入和删除等,且支持预编译的参数化SQL语句,有效防止SQL注入攻击。 以下是一个简单的SpringMVC结合JdbcTemplate的示例: 1. 配置SpringMVC:在`web.xml`中配置...

    Spring+hibernate整合源代码

    Spring 可以通过工厂方法或 JdbcTemplate、HibernateTemplate 提供的模板方法来获取 Session。 6. **Service 层设计**:Service 层是业务逻辑的核心,通常会注入 DAO 实例并调用其方法来完成业务处理。Service 层...

    Struts2+Spring+EasyUI+JDBCTemplate学习源码

    Struts2、Spring、EasyUI和JDBCTemplate是Java Web开发中常用的技术栈,它们在构建企业级应用中发挥着关键作用。这个压缩包提供了一个整合这些技术的学习示例,便于初学者理解和实践。 首先,Struts2是一个基于MVC...

    打印JdbcTemplate执行sql

    这篇博客文章的标题"打印JdbcTemplate执行sql"主要涉及如何在使用`JdbcTemplate`时,追踪并打印出执行的SQL语句,这对于调试和性能分析非常有帮助。接下来,我们将深入探讨`JdbcTemplate`的工作原理以及如何实现SQL...

    spring-jdbcTemplate实例工程

    《深入解析Spring JdbcTemplate》 Spring JDBC Template是Spring框架中用于简化JDBC操作的一个核心组件,它是Spring对JDBC API的封装,旨在提供一个更加简洁、健壮且可测试的数据库访问层。在这个实例工程中,我们...

    jdbcTemplate分页彻底解决,使用游标滚动

    在Java的Spring框架中,`JdbcTemplate`是一个非常重要的组件,它...通过阅读和理解`JdbcTemplateExtend.java`和`SplitPageResultSetExtractor.java`的源码,我们可以更深入地了解这一机制,并将其应用到实际项目中。

    SpringJdbcTemplate封装工具类

    "更新记录.docx"文件可能是项目开发过程中对SpringJdbcTemplate封装工具类的修改日志,记录了每次更新的功能改进、bug修复或性能优化等内容,这对于版本管理和问题排查非常有帮助。 通过上述分析,我们可以看到...

    jdbcTemplate

    6. **回调接口**:通过`PreparedStatementCreator`和`ResultSetExtractor`等回调接口,用户可以在不修改`JdbcTemplate`核心逻辑的情况下定制SQL执行和结果处理。 7. **执行效率**:由于`JdbcTemplate`会缓存预编译...

    springboot源码解析视频

    本视频课程专注于SpringBoot的源码解析,旨在帮助开发者深入理解其内部工作原理,提升对SpringBoot的掌控力。 1. **SpringBoot核心概念** - 自动配置:SpringBoot通过`@EnableAutoConfiguration`注解自动配置应用...

    JdbcTemplate的事务控制.docx

    ### JdbcTemplate 的事务控制 #### 一、引言 在软件开发过程中,事务管理是非常重要的一个环节,尤其是在处理数据库操作时。事务能够确保一系列数据库操作要么全部成功,要么全部失败,从而保持数据的一致性和完整...

    Spring JdbcTemplate 常用方法整理

    本文将深入探讨Spring JdbcTemplate的常用方法,并结合提供的`JsonBean.java`和`JdbcUtils.java`文件,来理解其在实际应用中的使用。 首先,JdbcTemplate的核心功能在于它提供了一系列的方法来执行SQL语句,包括...

    Spring--JdbcTemplate.pdf

    标签"spring 尚硅谷 JdbcTemplate"说明这个文档可能是由"尚硅谷"发布,"尚硅谷"是一家专注于IT教育和培训的机构,他们提供的文档可能会对Spring框架及其JdbcTemplate的使用有详细的讲解和实例。 在介绍JdbcTemplate...

    springboot+JdbcTemplate+druid

    在本项目中,我们关注的是如何在 Spring Boot 应用程序中集成 JdbcTemplate 和 Druid 数据源来实现数据库操作。 JdbcTemplate 是 Spring 框架的一部分,提供了一个方便的 API 来执行 SQL 查询和更新,避免了手动...

Global site tag (gtag.js) - Google Analytics