Hibernate延迟加载:
Hibernate 对象关系映射提供延迟的与非延迟的对象初始化。非延迟加载在读取一个对象的时候会将与这个对象所有相关的其他对象一起读取出来。这有时会导致成百的(如果不是成千的话) select 语句在读取对象的时候执行。这个问题有时出现在使用双向关系的时候,经常会导致整个数据库都在初始化的阶段被读出来了。当然,你可以不厌其烦地检查每一个对象与其他对象的关系,并把那些最昂贵的删除,但是到最后,我们可能会因此失去了本想在 ORM 工具中获得的便利。
一个明显的解决方法是使用 Hibernate 提供的延迟加载机制。这种初始化策略只在一个对象调用它的一对多或多对多关系时才将关系对象读取出来。这个过程对开发者来说是透明的,而且只进行了很少的数据库操作请求,因此会得到比较明显的性能提升。这项技术的一个缺陷是延迟加载技术要求一个 Hibernate 会话要在对象使用的时候一直开着。这会成为通过使用 DAO 模式将持久层抽象出来时的一个主要问题。为了将持久化机制完全地抽象出来,所有的数据库逻辑,包括打开或关闭会话,都不能在应用层出现。最常见的是,一些实现了简单接口的 DAO 实现类将数据库逻辑完全封装起来了。一种快速但是笨拙的解决方法是放弃 DAO 模式,将数据库连接逻辑加到应用层中来。这可能对一些小的应用程序有效,但是在大的系统中,这是一个严重的设计缺陷,妨碍了系统的可扩展性。
在 Web 层进行延迟加载
幸运的是, Spring 框架为 Hibernate延迟加载与 DAO 模式的整合提供了一种方便的解决方法。对那些不熟悉 Spring 与 Hibernate 集成使用的人,我不会在这里讨论过多的细节,但是我建议你去了解 Hibernate 与 Spring 集成的数据访问。以一个 Web 应用为例, Spring 提供了 OpenSessionInViewFilter 和 OpenSessionInViewInterceptor 。我们可以随意选择一个类来实现相同的功能。两种方法唯一的不同就在于 interceptor 在 Spring 容器中运行并被配置在 web 应用的上下文中,而 Filter 在 Spring 之前运行并被配置在 web.xml 中。不管用哪个,他们都在请求将当前会话与当前(数据库)线程绑定时打开 Hibernate 会话。一旦已绑定到线程,这个打开了的 Hibernate 会话可以在 DAO 实现类中透明地使用。这个会话会为延迟加载数据库中值对象的视图保持打开状态。一旦这个逻辑视图完成了, Hibernate 会话会在 Filter 的 doFilter 方法或者 Interceptor 的 postHandle 方法中被关闭。下面是每个组件的配置示例:
Interceptor的配置:
< beans >
< bean id ="urlMapping" class ="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
< property name ="interceptors" >
< list >
< ref bean ="openSessionInViewInterceptor" />
< / list >
< / property >
< property name ="mappings" >
< / bean >
< bean name ="openSessionInViewInterceptor" class ="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor" >
< property name ="sessionFactory" >
< ref bean ="sessionFactory" />
< / property >
< / bean >
< / beans >
Filter的配置
< web-app >
< filter >
< filter-name > hibernateFilter < / filter-name >
< filter-class >org.springframework.orm.hibernate.support.OpenSessionInViewFilter < / filter-class >
< / filter >
< filter-mapping >
< filter-name > hibernateFilter < / filter-name >
< url-pattern > *. spring < / url-pattern >
< / filter-mapping >
< / web-app >
实现 Hibernate 的 Dao 接口来使用打开的会话是很容易的。事实上,如果你已经使用了 Spring 框架来实现你的 Hibernate Dao, 很可能你不需要改变任何东西。方便的 HibernateTemplate 公用组件使访问数据库变成小菜一碟,而 DAO 接口只有通过这个组件才可以访问到数据库。下面是一个示例的 DAO :
public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO {
public Product getProduct(Integer productId) {
return (Product)getHibernateTemplate().load(Product. class , productId); }
public Integer saveProduct(Product product) {
return (Integer) getHibernateTemplate().save(product); }
public void updateProduct(Product product) { getHibernateTemplate().update(product); }
}
在业务逻辑层中使用Hibernate延迟加载 即使在视图外面, Spring 框架也通过使用 AOP 拦截器 HibernateInterceptor 来使得延迟加载变得很容易实现。这个 Hibernate 拦截器 透明地将调用配置在 Spring 应用程序上下文中的业务对象中方法的请求拦截下来,在调用方法之前打开一个 Hibernate 会话,然后在方法执行完之后将会话关闭。让我们来看一个简单的例子,假设我们有一个接口
BussinessObject :
public interface BusinessObject {
public void doSomethingThatInvolvesDaos(); } 类BusinessObjectImpl实现了BusinessObject接口:
public class BusinessObjectImpl implements BusinessObject {
public void doSomethingThatInvolvesDaos() { // lots of logic that calls // DAO classes Which access // data objects lazily }
}
通过在Spring应用程序上下文中的一些配置,我们可以让将调用BusinessObject的方法拦截下来,再令它的方法支持延迟加载。看看下面的一个程序片段:
< beans >
< bean id ="hibernateInterceptor" class ="org.springframework.orm.hibernate.HibernateInterceptor" >
< property name ="sessionFactory" >
< ref bean ="sessionFactory" />
< / property >
< / bean >
< bean id ="businessObjectTarget" class ="com.acompany.BusinessObjectImpl" >
< property name ="someDAO" >
< ref bean ="someDAO" />
< / property >
< / bean >
< bean id ="businessObject" class ="org.springframework.aop.framework.ProxyFactoryBean" >
< property name ="target" >
< ref bean="businessObjectTarget" />
< / property >
< property name ="proxyInterfaces" >
< value > com.acompany.BusinessObject < / value >
< / property >
< property name ="interceptorNames" >
< list >
< value > hibernateInterceptor < / value >
< / list >
< / property >
< / bean >
< / beans >
当 businessObject 被调用的时候, HibernateInterceptor 打开一个 Hibernate 会话,并将调用请求传递给 BusinessObjectImpl 对象。当 BusinessObjectImpl 执行完成后, HibernateInterceptor 透明地关闭了会话。应用层的代码不用了解任何持久层逻辑,还是实现了延迟加载。
在单元测试中测试Hibernate延迟加载
最后,我们需要用 J-Unit 来测试我们的延迟加载程序。我们可以轻易地通过重写 TestCase 类中的 setUp 和 tearDown 方法来实现这个要求。我比较喜欢用这个方便的抽象类作为我所有测试类的基类。
public abstract class MyLazyTestCase extends TestCase {
private SessionFactory sessionFactory;
private Session session;
public void setUp() throws Exception {
super .setUp();
SessionFactory sessionFactory = (SessionFactory) getBean( " sessionFactory " );
session = SessionFactoryUtils.getSession(sessionFactory, true );
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, newSessionHolder(s));
}
protected Object getBean(String beanName) { // Code to get objects from Spring application context }
public void tearDown() throws Exception {
super .tearDown();
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory); } }
分享到:
相关推荐
- **懒加载(Lazy Loading)**:Hibernate支持关联对象的延迟加载,避免一次性加载大量数据。 - **批处理**:Spring可以设置批处理大小,批量处理数据库操作,提升效率。 7. **测试与调试** - **单元测试**:...
8. **处理Hibernate延迟加载**:使用`OpenSessionInViewFilter`过滤器,确保Session在整个HTTP请求期间保持打开状态,解决懒加载问题。配置过滤器映射到所有.do请求。 9. **处理只读模式异常**:由于...
2. **Spring ORM/DAO/Hibernate3库**:这些库允许Spring与Hibernate进行交互,提供了对Hibernate的封装和管理,使得我们可以在Spring环境下使用Hibernate进行数据操作。 3. **Spring AOP库**:AOP库用于实现切面...
10. **性能优化**:整合Spring和Hibernate后,我们可以通过配置和最佳实践优化性能,如批量操作、延迟加载、缓存策略等。 总的来说,Spring整合Hibernate能带来更优雅的代码结构、强大的事务管理和灵活的数据库操作...
它支持延迟加载、缓存机制、事务管理等高级特性,大大简化了数据库操作。 **Spring2.5** 是一个全面的后端应用框架,核心功能包括依赖注入(DI)和面向切面编程(AOP)。Spring提供了一个容器来管理应用对象的生命...
它支持延迟加载,避免了大量数据一次性加载导致的性能问题,还有强大的查询语言HQL(Hibernate Query Language)和 Criteria API,使得数据库查询更加灵活。 **SSH整合**: SSH整合的关键在于如何协调这三个框架的...
10. **处理Hibernate延迟加载问题**:为了解决由于Session生命周期和HTTP请求生命周期不匹配导致的延迟加载问题,可以使用OpenSessionInViewFilter。这个过滤器确保Session在请求结束时才关闭,从而能正确处理延迟...
7. **延迟加载**:Hibernate的懒加载机制,只有当真正需要访问关联对象时,才会发起数据库查询,有效避免了“n+1”查询问题。 8. **事务管理**:在SSH框架中,Spring负责事务管理,可以设置不同的事务隔离级别和...
通过使用Hibernate,我们可以避免编写大量的JDBC代码,同时利用其高级特性,如延迟加载、事务管理和缓存支持。 **整合Struts与Hibernate** 在Struts和Hibernate的整合中,通常Struts作为前端控制器,负责接收HTTP...
JPA2带来了许多改进,如支持双向一对多关联、延迟加载优化、查询注解增强等。而Hibernate4是JPA的一个流行实现,它提供了更丰富的功能,如第二级缓存、事务管理和事件监听器。 在Eclipse中创建Dynamic Web Project...
Spring与Struts2和Hibernate可以很好地整合,提供了一个称为Spring MVC的Web框架,它同样遵循MVC模式,但具有更现代的设计和更好的组件解耦。 整合Struts2和Hibernate,通常会利用Spring的IoC容器管理Action和DAO...
3. **实体生命周期管理**:支持了预加载(pre-fetching)和延迟加载(lazy-loading),以及更灵活的实体状态管理,比如“脱管”(detached)状态。 4. **更丰富的类型支持**:包括对数组、集合和自定义类型的支持,...
2. **延迟加载**:只在需要时加载数据,提高性能。 3. **Criteria查询**:提供面向对象的查询方式,更易读写。 4. **HQL(Hibernate Query Language)**:面向对象的查询语言,类似SQL。 5. **二级缓存**:支持...
7. **懒加载和级联操作**: Hibernate支持对象关系的懒加载,通过`lazy="true"`可以延迟加载关联数据。级联操作允许在一次主对象的操作中处理相关联的对象,如`CascadeType.ALL`表示对关联对象的所有操作都进行级联。...
Hibernate包含许多高级特性,如缓存机制(一级缓存和二级缓存)、事务管理、事件监听、延迟加载等,这些特性可以显著提升性能和应用的灵活性。 ### 6. Hibernate最佳实践 - 使用注解进行对象-关系映射,减少XML...
此外,孙卫琴女士的讲解可能涵盖了Hibernate与其他技术的整合,如Spring框架、MyBatis等,以及如何进行性能调优,包括查询优化、减少N+1查询问题、合理使用缓存等。通过她的指导,开发者可以更高效地利用Hibernate,...
通过实际的项目案例,学习如何在Java应用中整合Hibernate,创建数据模型,编写DAO层,设计服务层,最后进行测试验证。案例涵盖了从简单的增删改查到复杂的关联查询和事务管理,让学习者能将理论知识转化为实际技能。...
12. ** Hibenate与Spring的整合**:介绍如何在Spring框架中集成Hibernate,利用Spring的事务管理,实现DAO和Service层的解耦。 13. **案例分析**:通过实际例子演示如何在项目中应用Hibernate,解决具体问题。 每...
15. **Hibernate与其他技术的整合**:如Spring框架的整合,使用Hibernate的DAO和Service层设计模式,以及JSF、Struts等Web框架的集成。 《Hibernate中文帮助PDF》详尽地解析了这些知识点,是开发者学习和掌握...