spring可以方便的集成Hibernate,用它来管理顶层的JTA,同时使用Hibernate的持久化。在spring很容易划分和声明事物。但问题是:Hibernate有时需要探查当前Current transaction)的事物,这些都需要配置。在应用程序中使用auto flushing致使我们很难探查这些bugs。
Auto flushing
whats that?
它是Hibernate中一个特性,当一个query 被执行,在memory中的数据同步到数据库中。
一般情况下,当session被flushed 后,H 仅仅将会从内存同步到 DB.
看看这段代码
public void transactionInterceptedMethod() {
Person p = new Person("Maarten");
personDao.save(p);
List<Person> persons = personDao.findAll();
}
注意:他们是在一个事务中.和所说的一般情况一样
这个new person 是否会在 list中返回了?这取决于spring 和Hibernate的配置。
1.这个对象将不会立刻插入数据库,它保持在内存中,until session is flushed。
2.findAll方法使用的和Insert方法使用的same trasaction。要查到这个new person,至少要在insert transaction执行之前。
3.spring将会在这个方法结束前才会让hibernate提交trasaction。
我们主要针对insert和findAll方法之间的session flushed进行讨论。
设置Hibernate的session为“Auto”,H会检查在内存中是否有改变是否会影响Query,如果有,将会把内存数据同步到数据库中。虽然H的Auto-flushing很自动,来支持查询,但不它不会总是flush,这是对性能的考虑。
有两种可能办法可以解决这些:
1.在Hibernate直接配置
2.通过spring配置Hibernate
使用hibernate.transaction.manager_lookup_class 和hibernate.transaction.factory_class.
虽然他们将被Hibernate用来启动线程,但是我们仅仅打算用它探测他们
通过Spring 注入一个taTransactionManager 到LocalSessionFactoryBean.这依赖于你spring使用的版本,另外设置必须改变。
原理请看原文:
Spring is a great framework for dependency injection and it comes with a lot of support classes and utilities for all kind of things. Hibernate is a persistence service with a lot of useful features, that is relatively easy to use. Configuring both frameworks is not always easy. Configuring them together is sometimes hard and it is easy to make mistakes.
This blog addresses a problem in a configuration that is fairly common: use Spring for transaction management on top of a JTA provider and use Hibernate for persistence. Transaction demarcation is easy and declarative with Spring. The problem is that Hibernate sometimes needs to detect the current transaction and this needs to be configured. This leads to hard to detect bugs in applications that rely on auto flushing.
Auto Flushing
Auto flushing is a Hibernate feature which will synchronize in-memory state with database state when a query is executed. Normally, Hibernate will only synchronize in-memory and database state when the session is flushed. With Spring this can be configured to occur when the transaction is committed. This might lead to unexpected behaviour. Look at the code below
public void transactionInterceptedMethod() {
Person p = new Person("Maarten");
personDao.save(p);
List<Person> persons = personDao.findAll();
}
Will the new person be in the list of persons? I think everybody would suspect so. In fact, this relies heavily on how Spring and Hibernate are configured.
The person object will not immediately be inserted into the database when offered to Hibernate. It will be kept in memory, until the session is flushed. (There are exceptions, but this is the general rule).
The findAll method will look in the database in the same transaction as the one that is used to insert the person object. Still it will only find the new person if it has been inserted into the database in the same transaction before the query is made.
Spring will commit the transaction and instruct Hibernate to flush the current session only at the end of the method.
All these circumstances influence the result of the findAll method. It seems that we can only have the new person object in the list if we flush the session between the save and findAll methods.
This is where auto flushing comes in. When the flush mode of the session is set to "AUTO", Hibernate will inspect the in-memory state to see if there are any changes that might influence the result of any query that it is about to execute. If Hibernate determines this is so, it will flush the session, synchronizing the in-memory state and the database state. This will not alter the transactional status, but inly execute some SQL statements within the current transactional context.
Auto-flushing is quite intelligent in what to flush when, although some situations might be hard to detect. To improve performance, Hibernate will not simply always flush everything, but look at the tables in the database that the query touches and the data in-memory that should be stored in those tables. If there is no overlap, no data will be persisted. If an overlap is found, the whole session will be flushed, to ensure consistency.
Spring, JTA and transaction detection
Now this all seems to work out fine, but what does it have to do with Spring, JTA or transaction detection? Well, Hibernate will only perform auto flushing if it detects that there is a transaction running. It is not completely clear to me why it won't do the flushing, but this is how it works. It has a number of strategies for detecting that there is a transaction. The default strategy is to look at its own transaction mechanism.
When using Spring, to manage transactions, using Hibernates mechanism for transactions (which is a thin layer on top of JDBC) is an option. This mechanism does not support distributed transactions. To support distributed transactions, Spring says you can just drop in their JtaTransactionManager to replace the HibernateTransactionManager. This is not completely true though: It will work seamlessly for transaction demarcation, but not for transaction detection through hibernate.
Transaction demarcation will work fine: Spring will start a new Hibernate session whenever a transaction is started. Hibernate will work with that session, oblivious of the transaction that has been opened. This is not a problem for demarcation: Spring will flush and close the session when the transaction is closed.
For Hibernates transaction detection it does not work: Hibernate is oblivious to the Spring started transaction and it will not do auto flushing. There are not many features in Hibernate that depend upon transaction detection, so this misbehavior of the system might go undetected for quite a while. The problem with auto flushing is that it is not always as simple as two consecutive lines doing a save and findAll. The logic that saves an entity and the logic that depends upon the entity being found by a query within the same transaction might be in separate classes, only connected by a typical flow.
Solution
So how do we tell Hibernate what strategy to use for transaction detection? There are two possibilities: 1) configure Hibernate directly or 2) configure Hibernate through Spring.
To configure Hibernate directly, use the hibernate.transaction.manager_lookup_class and hibernate.transaction.factory_class. These properties would be used by Hibernate to start transactions, but we're not starting transactions through Hibernate, just detecting them.
To configure Hibernate through Spring, inject a JtaTransactionManager into the LocalSessionFactoryBean. Depending on the specific version of Spring you are using, additional settings must be changed.
Conclusion
Developing with powerful frameworks like Spring and Hibernate makes many tasks easy. It is of great importance that the frameworks are correctly configured, especially if they need to work together. I hope blog will help you detect a particular small bug in your configuration, that could lead to severe problems.
分享到:
相关推荐
《Spring、Hibernate与JTA在MyEclipse中的整合实践》 在现代企业级应用开发中,Spring、Hibernate和Java Transaction API(JTA)是常见的技术组合。Spring作为轻量级的IoC(Inversion of Control)和AOP(Aspect ...
Spring、Hibernate和JTA(Java Transaction API)是Java开发者在构建分布式事务解决方案时常用的三大技术。本示例“第二部分spring+hibernate+jta 分布式事务Demo”将帮助我们理解如何在这三个框架之间协同工作,...
【标题】"JTA-demo:spring+hibernate+jta+mysql" 演示了在Java应用中如何使用Spring框架、Hibernate ORM工具以及Java Transaction API(JTA)来实现跨数据库的事务管理,同时结合MySQL数据库进行数据存储。...
以上就是Spring结合Druid和Hibernate,使用Atomikos实现JTA配置分布式事务的基本流程。在实际应用中,还需要考虑异常处理、事务隔离级别、事务的传播行为等因素,以满足不同业务场景的需求。同时,需要注意的是,...
3. **配置Hibernate**:配置Hibernate的`hibernate.cfg.xml`,设置JTA数据源,并指定使用Spring的事务管理。 4. **编写业务逻辑**:在你的服务类中,你可以利用Spring的@Autowired注解注入需要的bean,然后在方法上...
3. **配置Hibernate**:在Hibernate的配置文件中,设置`hibernate.transaction.jta.platform`属性为Spring的`PlatformTransactionManager`实现,让Hibernate知道使用Spring管理事务。 4. **声明式事务管理**:在...
1. **配置Hibernate**:在Spring的配置文件(如`applicationContext.xml`)中,定义SessionFactory Bean,指定Hibernate的相关属性,如配置文件路径、数据库连接信息等。 2. **配置Transaction Manager**:创建...
12.6.16 编写Spring和Hibernate的配置文件spring-config.xml 12.6.17 编写web.xml 12.6.18 验证示例 12.7 小结 第四篇 J2EE项目案例精选 第十三章 网上调查系统 13.1 系统概述 13.2 需求分析 13.2.1 系统用例图 ...
4. 配置Spring:在Spring的配置文件中,为每个数据源创建一个PlatformTransactionManager Bean,使用Atomikos的JtaTransactionManager。此外,还需要配置Atomikos的相关属性,如事务超时时间、日志位置等。 5. 业务...
在Spring 2.5 和 Hibernate 3.0 中,注解成为主要的配置方式。例如,`@Autowired` 注解用于依赖注入,`@Repository`、`@Service` 和 `@Controller` 用于组件扫描,`@Transactional` 用于声明式事务管理。在...
总的来说,Spring通过`LocalSessionFactoryBean`实现对Hibernate的驱动,它将数据源、事务管理和配置信息集成在一起,创建出适应Spring管理的`SessionFactory`。这种集成方式使得开发者无需过多关注底层细节,可以...
整合过程中,我们通常会配置Spring的XML配置文件来定义数据源、SessionFactory、事务管理器等,并使用Hibernate的SessionFactory来创建和管理Session。同时,通过Spring的声明式事务管理,可以在不侵入业务代码的...
- Spring还提供了对其他库的集成,如JDBC、JMS、JTA等,以及对其他框架如Hibernate、Struts2的整合支持。 2. **Hibernate框架**: - Hibernate是一个对象关系映射(Object-Relational Mapping,ORM)框架,它简化...
Spring、Hibernate和Struts是Java开发中的三大主流框架,它们分别负责不同的职责,共同构建了企业级应用的基础架构。Spring作为一个全面的轻量级容器,提供了依赖注入(DI)和面向切面编程(AOP)的功能,使得代码...
本项目使用Spring Boot、Atomikos、JTA(Java Transaction API)、Hibernate和MySQL来实现分布式事务处理和多数据源管理,以确保在多个数据库操作之间保持事务的ACID特性。 首先,Spring Boot作为微服务开发的主流...
在Java开发领域,Spring和Hibernate是两个非常重要...同时,注意版本兼容性,因为不同版本的Spring和Hibernate可能有不兼容的问题。通过合理选择和配置这些jar包,可以有效地提升开发效率,实现高效稳定的企业级应用。