惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
NISL@THU
NISL@THU
E
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
K
Kaspersky official blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
S
Schneier on Security
G
GRAHAM CLULEY
The Hacker News
The Hacker News
T
Threat Research - Cisco Blogs
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
爱范儿
爱范儿
P
Privacy International News Feed
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
S
Securelist
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
美团技术团队
F
Fortinet All Blogs
小众软件
小众软件
Recorded Future
Recorded Future
V
Visual Studio Blog
B
Blog RSS Feed
H
Help Net Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Martin Fowler
Martin Fowler
Latest news
Latest news
Spread Privacy
Spread Privacy
H
Heimdal Security Blog

博客园 - 不明飞行物

磨刀不误砍柴工-打造超级Symbian开发环境 Symbian OS 开发初级手册 (8) 多线程 Symbian OS 开发初级手册 (7) Descriptors - 不明飞行物 Symbian OS 开发初级手册 (6) CleanupStack and Two-phase Symbian OS 开发初级手册 5 - Leave Symbian OS 开发初级手册 (4) mmp, pkg 文件 和 makesis 工具 Symbian OS 开发初级手册 (3)GUI程序中的4个基本类 Symbian OS 开发初级手册 (2)基本数据类型 Symbian OS 开发初级手册 (1) Introduction 利用JavaMail收/发Gmail邮件(SSL) Tapestry4在提交前判断checkbox是否没有一个被选中 - 不明飞行物 - 博客园 恢复windows的引导程序 在页面中插入Windows Media Player播放器 - 不明飞行物 Java中Set的深入研究 - 不明飞行物 - 博客园 用spring管理hibernate事务时,lzay="true"不能用的解决方法 java中List和Set对象的互换 Tapestry4.0中取得页面request - 不明飞行物 - 博客园 Logout in tapesty4.0 - 不明飞行物 validators里自定义错误信息 - 不明飞行物 - 博客园
Hibernate和Spring的延迟加载和DAO模式
不明飞行物 · 2006-01-11 · via 博客园 - 不明飞行物

转载于:http://spaces.msn.com/members/zcgly/Blog/cns!1pQwDnSfBx4siamZpHR2gqMQ!121.entry

时间:2005-07-13

Hibernate和延迟加载
Hibernate对象关系映射提供了两种对象初始化模式:延迟加载和非延迟加载。非延迟加载在加载时获取对象本身以及它关联的所有对象

。这可能导致在获取一个实例时,执行成百上千的select语句。当使用双向关联时,这个问题被放大,常常出现初始化请求时,整个数据

库都被载入。显然检查每个对象的关系,并手工删除他们会费点事,但最终我们可能会因此丢失使用ORM工具的优势。

一个明细的解决方式是使用hibernate提供的延迟载入机制。这种初始化策略在类成员被访问时只载入它的一个对象的一对多和多对多关

系。对开发人员来说,这种方式是透明的,并且只有最少数量的请求发生,这样就获得了最佳的性能。这种技术的一个缺点是延迟载入要

求当对象还在使用中时,Hibernate的Session必须保持打开状态。当尝试通过DAO模式抽象持久层时,这会引起一个重要问题。为了充分

地抽象持久层,所有的数据库逻辑,包括打开、关闭Session都不能在应用层出现。最常见的是,这些逻辑隐藏在DAO的实现类中。快速和

差一些的方案是:避免采用DAO模式,在应用层中包含数据连接的逻辑。这在小应用中是可行的,但在大系统中,这会是一个设计缺陷,

它损害了应用的扩展性。

在Web层使用延迟加载
幸运的是,Spring框架已经提供了一个DAO模式结合Hibernate延迟加载的Web方案。对于任何不熟悉Spring框架结合Hibernate人来说,我

在这里不会深入细节,但是我希望你去阅读“结合Spring框架的Hibernate数据库访问”章节。这个案例是一个Web应用,Spring提供了

OpenSessionInViewerFilter和OpenSessionInViewInterceptor。使用它们中的任一个都能获得同样的功能。这两者唯一不同的是

interceptor在Spring容器中运行,并且在web应用的上下文中配置;fitler在Spring前运行,并且在web.xml中配置。不管使用哪一个,

他们都会在请求绑定到Session的当前线程期间打开Hibernate Session。一旦绑定到线程,打开的Hibernate Session能被DAO的实现类透

明地使用。Session会持续打开允许延迟加载访问数据库。一旦View逻辑完成,hibernate session会被关闭,无论是在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>
使用打开的session的HibernateDAO实现类很简单。实际上,如果你已经使用Spring框架实现Hibernate的DAO对象,最有可能的是,你不

需要做任何改动。DAO必须通过方便的HibernateTemplate工具访问Hibernate,这对数据库访问来说就是小菜一碟。下面是一个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);
       }
 }

在业务层使用延迟加载
甚至在表现层外,Spring框架也通过AOP拦截器HibernateInterceptor提供了便利的延迟加载支持。hibernate拦截器透明地拦截了配置在

Spring应用上下文中的业务对象的调用,在调用前打开hibernate session,在调用结束时关闭这个session。让我们通过一个简单的例子

来说明。假设我们有一个interface叫做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上下文的一些配置,我们可以让HibernateInterceptor拦截对BusinessObjectImpl的调用,允许它的方法延迟访问数据对象。

看一下下面的片断:
<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 session并允许对BussinessObjectImpl的调用。当

BusinessOjbectImpl执行完成,HibernateInterceptor透明的关闭这个session。应用代码并不知道任何持久层逻辑,但它仍然能够使用

延迟加载访问数据对象。

在单元测试中使用延迟加载
最后,我们要在JUnit中测试我们的延迟加载应用。覆盖TestCase类的setUp和tearDown方法非常容易。我更喜欢将这段代码放在一个简便

的抽象TestCase类中,作为我所有测试的基类。
public abstract class MyLazyTestCase extends TestCase {


 

        public void setUp() throws Exception {
     super.setUp();
     SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory");
     Session s = sessionFactory.openSession();
     TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(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);
        }
}