- 浏览: 5077168 次
- 性别:
- 来自: 南京
-
文章分类
- 全部博客 (2844)
- java (1094)
- hadoop (37)
- jvm (39)
- hbase (11)
- sql (25)
- 异常 (83)
- div css (6)
- 数据库 (95)
- 有趣的code (15)
- struts2 (6)
- spring (124)
- js (44)
- 算法 (65)
- linux (36)
- hibernate (7)
- 中间件 (78)
- 设计模式 (2)
- 架构 (275)
- 操作系统 (91)
- maven (35)
- tapestry (1)
- mybatis (9)
- MQ (101)
- zookeeper (18)
- 搜索引擎,爬虫 (208)
- 分布式计算 (45)
- c# (7)
- 抓包 (28)
- 开源框架 (45)
- 虚拟化 (12)
- mongodb (15)
- 计算机网络 (2)
- 缓存 (97)
- memcached (6)
- 分布式存储 (13)
- scala (5)
- 分词器 (24)
- spark (104)
- 工具 (23)
- netty (5)
- Mahout (6)
- neo4j (6)
- dubbo (36)
- canal (3)
- Hive (10)
- Vert.x (3)
- docker (115)
- 分布式追踪 (2)
- spring boot (5)
- 微服务 (56)
- 淘客 (5)
- mesos (67)
- php (3)
- etcd (2)
- jenkins (4)
- nginx (7)
- 区块链 (1)
- Kubernetes (92)
- 驾照 (1)
- 深度学习 (15)
- JGroups (1)
- 安全 (5)
- 测试 (16)
- 股票 (1)
- Android (2)
- 房产 (1)
- 运维 (6)
- 网关 (3)
最新评论
-
明兜3号:
部署落地+业务迁移 玩转k8s进阶与企业级实践技能(又名:Ku ...
Kubernetes系统常见运维技巧 -
q328965539:
牛掰啊 资料收集的很全面
HDFS小文件处理解决方案总结+facebook(HayStack) + 淘宝(TFS) -
guichou:
fluent挂载了/var/lib/kubelet/pods目 ...
kubernetes上部署Fluentd+Elasticsearch+kibana日志收集系统 -
xu982604405:
System.setProperty("java.r ...
jmx rmi 穿越防火墙问题及jmxmp的替代方案 -
大漠小帆:
麻烦问下,“获取每个Item相似性最高的前N个Item”,这个 ...
协同过滤推荐算法在MapReduce与Spark上实现对比
由于项目中对批量的sql进行入库处理。所以打算用jdbcTemplate。在其他的增删改查中都是用hibernateTemplate。
在这里考虑到一个问题,就是当jdbcTemplate和hibernateTemplate结合用的时候,事物是怎么样的了?
经过测试:在一个方法中同时使用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");
在OpenEntityManagerInViewFilter,OpenSessionInViewInterceptor等需要获取当前线程对象的类中都用到了此类。
在使用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对象是同一对象时,基本上证明了在使用jdbcTemplate和hibernateTemplate的时候。
在事物的完整性方面来说是没有问题的。下面我们在看看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代理如何起作用时,我们知道Spring的AOP代理通过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 {
//这里调用的是: AbstractPlatformTransactionManager的rollback方法。最终调用的相应的子类的doRollback方法。
// 比如用的是hibernateTranactionManager就是调用其中的doRollback方法。
// txObject.getSessionHolder().getTransaction().rollback();这里最终调用的还是Hibernate中Transaction的Rollback方法
//归根揭底,都是调用了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;
/* */ }
/* */ }
评论
总结:使用jdbcTemplate和hibernateTemplate拥有一样的统一的事物一致性,可以放心的结合使用。
放心的结合使用不能这样说啊。。如果不牵扯到hibrnate的缓存的话,可以放心使用。如果同时对缓存对象操作的话,hibernate的缓存不能及时更新,会有问题的。
呵呵,也是,不过查询的话,倒是可以放心使用就是。
总结:使用jdbcTemplate和hibernateTemplate拥有一样的统一的事物一致性,可以放心的结合使用。
放心的结合使用不能这样说啊。。如果不牵扯到hibrnate的缓存的话,可以放心使用。如果同时对缓存对象操作的话,hibernate的缓存不能及时更新,会有问题的。
总结:使用jdbcTemplate和hibernateTemplate拥有一样的统一的事物一致性,可以放心的结合使用。
发表评论
-
spring session序列化问题排查
2017-12-01 19:07 6321严重: Servlet.service() for ser ... -
spring mvc统一异常处理(@ControllerAdvice + @ExceptionHandler)
2017-12-01 17:09 3031spring 封装了非常强大的异常处理机制。本文选取@Co ... -
springboot注解
2017-12-01 09:44 1052@RestController和@RequestMappin ... -
Spring 4 xml 注解配置谅解
2017-12-01 09:39 1152《Spring in Action》4th E ... -
利用junit对springMVC的Controller进行测试
2017-11-30 16:26 1478平时对junit测试service/D ... -
spring cloud config实现datasource的热部署
2017-11-21 16:44 1652关于spring cloud config的基本使用,前面的 ... -
Spring+MyBatis实现数据库读写分离方案
2017-11-20 17:15 1146百度关键词:spring mybatis 多数据源 读写分离 ... -
spring session 退出登录 清理session
2017-11-10 09:26 6489/** * Allows creating an ... -
spring http session 监听 创建 失效session
2017-11-15 09:35 4900一.流程概述 主要是通过扩展ServletRequest ... -
spring session spring:session:sessions:expires 源码跟踪
2017-11-14 09:37 1544/** * Saves any attribut ... -
spring session 考虑问题解答
2017-11-09 09:50 677相关问题 2.Redis容量考虑,由于spring see ... -
spring 获取bean 测试
2017-11-09 09:51 697package com.jayway.springsess ... -
spring父子容器与读取properties文件
2017-11-09 09:51 845读取properties文件中的内容,可以使用@Value ... -
Spring在代码中获取bean的几种方式
2017-11-08 09:46 1255方法一:在初始化时保存ApplicationContext对 ... -
Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
2017-11-08 09:41 844解释一: 要想很好理解这三个上下文的关系,需 ... -
Spring以及SPringmvc相关问题: ServletContext -父子容器
2017-11-08 09:41 639总结如下: 明确了Servlet规范中Servl ... -
DelegatingFilterProxy
2017-11-08 09:48 1239摘要: 配置过滤器代理类,通过spring配置的bean来 ... -
DelegatingFilterProxy-api
2017-11-09 09:51 585为什么用DelegatingFilterProxy ... -
spring的启动过程——spring和springMVC父子容器的原理
2017-11-15 09:29 744要想很好理解这三个上下文的关系,需要先熟悉spri ... -
spring中bean被多次实例化问题
2017-11-13 09:33 52591. 描述 spring中提供了两种主要方式实例化bea ...
相关推荐
本篇将深入探讨Spring JDBCTemplate的使用及其源码解析,帮助你理解其背后的机制。 首先,让我们了解在不使用JDBCTemplate时,传统的JDBC操作通常涉及以下步骤:加载驱动、建立数据库连接、创建Statement或...
Spring框架是目前Java企业级应用开发中最流行的技术之一,它以依赖注入和面向切面编程为特点,使得Java应用开发更加灵活、方便。...它的源码对于初学者理解框架的工作原理和应用开发流程具有很好的参考价值。
《Spring源码解析》PDF是一份深入探讨Spring框架核心机制的文档,主要涵盖了Spring的IoC容器、JDBC、MVC、AOP、声明式事务处理、与Hibernate的集成以及Acegi(现为Spring Security)框架的鉴权和授权等多个关键模块...
本资源包含了两个子项目,分别进行了springboot+jpa+jdbcTemplate的多数据源独立事务配置和jta分布式事务配置,并针对不同的情况编写了事务配置测试接口,还演示了JPA的domain一对多自动生成数据库表且不生成数据库...
通过本章节的学习,您应该能够掌握如何使用JdbcTemplate进行基本的数据库操作,以及如何在Spring中配置和使用声明式事务来管理复杂的业务流程。这些技能对于开发基于Spring框架的应用程序至关重要。
Spring提供了多种持久化模板,如JdbcTemplate和HibernateTemplate,以简化数据库操作并减少代码中的样板代码。这两个模板都是Spring JDBC模块的一部分,用于增强对SQL数据库的访问能力。本文将深入探讨Spring对...
JdbcTemplate支持多种操作,包括查询、更新、插入和删除等,且支持预编译的参数化SQL语句,有效防止SQL注入攻击。 以下是一个简单的SpringMVC结合JdbcTemplate的示例: 1. 配置SpringMVC:在`web.xml`中配置...
Spring 可以通过工厂方法或 JdbcTemplate、HibernateTemplate 提供的模板方法来获取 Session。 6. **Service 层设计**:Service 层是业务逻辑的核心,通常会注入 DAO 实例并调用其方法来完成业务处理。Service 层...
Struts2、Spring、EasyUI和JDBCTemplate是Java Web开发中常用的技术栈,它们在构建企业级应用中发挥着关键作用。这个压缩包提供了一个整合这些技术的学习示例,便于初学者理解和实践。 首先,Struts2是一个基于MVC...
这篇博客文章的标题"打印JdbcTemplate执行sql"主要涉及如何在使用`JdbcTemplate`时,追踪并打印出执行的SQL语句,这对于调试和性能分析非常有帮助。接下来,我们将深入探讨`JdbcTemplate`的工作原理以及如何实现SQL...
《深入解析Spring JdbcTemplate》 Spring JDBC Template是Spring框架中用于简化JDBC操作的一个核心组件,它是Spring对JDBC API的封装,旨在提供一个更加简洁、健壮且可测试的数据库访问层。在这个实例工程中,我们...
在Java的Spring框架中,`JdbcTemplate`是一个非常重要的组件,它...通过阅读和理解`JdbcTemplateExtend.java`和`SplitPageResultSetExtractor.java`的源码,我们可以更深入地了解这一机制,并将其应用到实际项目中。
"更新记录.docx"文件可能是项目开发过程中对SpringJdbcTemplate封装工具类的修改日志,记录了每次更新的功能改进、bug修复或性能优化等内容,这对于版本管理和问题排查非常有帮助。 通过上述分析,我们可以看到...
6. **回调接口**:通过`PreparedStatementCreator`和`ResultSetExtractor`等回调接口,用户可以在不修改`JdbcTemplate`核心逻辑的情况下定制SQL执行和结果处理。 7. **执行效率**:由于`JdbcTemplate`会缓存预编译...
本视频课程专注于SpringBoot的源码解析,旨在帮助开发者深入理解其内部工作原理,提升对SpringBoot的掌控力。 1. **SpringBoot核心概念** - 自动配置:SpringBoot通过`@EnableAutoConfiguration`注解自动配置应用...
### JdbcTemplate 的事务控制 #### 一、引言 在软件开发过程中,事务管理是非常重要的一个环节,尤其是在处理数据库操作时。事务能够确保一系列数据库操作要么全部成功,要么全部失败,从而保持数据的一致性和完整...
本文将深入探讨Spring JdbcTemplate的常用方法,并结合提供的`JsonBean.java`和`JdbcUtils.java`文件,来理解其在实际应用中的使用。 首先,JdbcTemplate的核心功能在于它提供了一系列的方法来执行SQL语句,包括...
标签"spring 尚硅谷 JdbcTemplate"说明这个文档可能是由"尚硅谷"发布,"尚硅谷"是一家专注于IT教育和培训的机构,他们提供的文档可能会对Spring框架及其JdbcTemplate的使用有详细的讲解和实例。 在介绍JdbcTemplate...
在本项目中,我们关注的是如何在 Spring Boot 应用程序中集成 JdbcTemplate 和 Druid 数据源来实现数据库操作。 JdbcTemplate 是 Spring 框架的一部分,提供了一个方便的 API 来执行 SQL 查询和更新,避免了手动...