﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Colorful Day-随笔分类-Spring</title><link>http://www.blogjava.net/blueoxygen/category/3745.html</link><description>Blue keywords,Green comment,Red breakpoint,my life is also colorful</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 02:55:33 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 02:55:33 GMT</pubDate><ttl>60</ttl><item><title>[导入]Hibernate Performance Tuning</title><link>http://www.blogjava.net/blueoxygen/archive/2006/03/16/35579.html</link><dc:creator>BlueO2</dc:creator><author>BlueO2</author><pubDate>Thu, 16 Mar 2006 03:19:00 GMT</pubDate><guid>http://www.blogjava.net/blueoxygen/archive/2006/03/16/35579.html</guid><wfw:comment>http://www.blogjava.net/blueoxygen/comments/35579.html</wfw:comment><comments>http://www.blogjava.net/blueoxygen/archive/2006/03/16/35579.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/blueoxygen/comments/commentRss/35579.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/blueoxygen/services/trackbacks/35579.html</trackback:ping><description><![CDATA[    <p><strong><font size="2">Hibernate and Lazy Initialization</font></strong> </p><p><font size="2">Hibernate object relational mapping offers both lazy and non-lazy modes of object initialization. Non-lazy initialization retrieves an object and all of its related objects at load time. This can result in hundreds if not thousands of select statements when retrieving one entity. The problem is compounded when bi-directional relationships are used, often causing entire databases to be loaded during the initial request. Of course one could tediously examine each object relationship and manually remove those most costly, but in the end, we may be losing the ease of use benefit sought in using the ORM tool. </font></p><p><font size="2">The obvious solution is to employ the lazy loading mechanism provided by hibernate. This initialization strategy only loads an object's one-to-many and many-to-many relationships when these fields are accessed. The scenario is practically transparent to the developer and a minimum amount of database requests are made, resulting in major performance gains. One drawback to this technique is that lazy loading requires the Hibernate session to remain open while the data object is in use. This causes a major problem when trying to abstract the persistence layer via the Data Access Object pattern. In order to fully abstract the persistence mechanism, all database logic, including opening and closing sessions, must not be performed in the application layer. Most often, this logic is concealed behind the DAO implementation classes which implement interface stubs. The quick and dirty solution is to forget the DAO pattern and include database connection logic in the application layer. This works for small applications but in large systems this can prove to be a major design flaw, hindering application extensibility.</font> </p><br/><link rel="stylesheet" type="text/css" href="http://blueoxygen.dflying.net/plugins/plogeshi/styles/plogeshi.css" /><p><strong><font size="2">Being Lazy in the Web Layer</font></strong> </p>
<p><font size="2">Fortunately for us, the Spring Framework has developed an out of box web solution for using the DAO pattern in combination with Hibernate lazy loading. For anyone not familiar with using the <a href="http://www.springframework.org/"><font color="#4a664d">Spring Framework</font></a> in combination with <a href="http://www.hibernate.org/"><font color="#4a664d">Hibernate</font></a>, I will not go into the details here, but I encourage you to read <a href="http://www.hibernate.org/110.html"><font color="#4a664d">Hibernate Data Access with the Spring Framework</font></a>. In the case of a web application, Spring comes with both the <a href="http://www.springframework.org/docs/api/org/springframework/orm/hibernate/support/OpenSessionInViewFilter.html"><font color="#4a664d">OpenSessionInViewFilter</font></a> and the <a href="http://www.springframework.org/docs/api/org/springframework/orm/hibernate/support/OpenSessionInViewInterceptor.html"><font color="#4a664d">OpenSessionInViewInterceptor</font></a>. One can use either one interchangeably as both serve the same function. The only difference between the two is the interceptor runs within the Spring container and is configured within the web application context while the Filter runs in front of Spring and is configured within the web.xml. Regardless of which one is used, they both open the hibernate session during the request binding this session to the current thread. Once bound to the thread, the open hibernate session can transparently be used within the DAO implementation classes. The session will remain open for the view allowing lazy access the database value objects. Once the view logic is complete, the hibernate session is closed either in the Filter doFilter method or the Interceptor postHandle method. Below is an example of the configuration of each component: </font></p>
<p><strong><font size="1">Interceptor Configuration</font></strong> </p>
</p>
<pre class="code"><span class="sc3"><span class="re1">&lt;beans<span class="re2">&gt;</span></span></span> 
  <span class="sc3"><span class="re1">&lt;bean</span> <span class="re0">id</span>=<span class="st0">"urlMapping"</span>     
     <span class="re0">class</span>=<span class="st0">"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"</span><span class="re2">&gt;</span></span>    
       <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">"interceptors"</span><span class="re2">&gt;</span></span>
         <span class="sc3"><span class="re1">&lt;list<span class="re2">&gt;</span></span></span>
              <span class="sc3"><span class="re1">&lt;ref</span> <span class="re0">bean</span>=<span class="st0">"openSessionInViewInterceptor"</span><span class="re2">/&gt;</span></span>
         <span class="sc3"><span class="re1">&lt;/list<span class="re2">&gt;</span></span></span>
       <span class="sc3"><span class="re1">&lt;/property<span class="re2">&gt;</span></span></span>
       <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">"mappings"</span><span class="re2">&gt;</span></span>
  ...
  <span class="sc3"><span class="re1">&lt;/bean<span class="re2">&gt;</span></span></span>
  ...
  <span class="sc3"><span class="re1">&lt;bean</span> <span class="re0">name</span>=<span class="st0">"openSessionInViewInterceptor"</span>  
    <span class="re0">class</span>=<span class="st0">"org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor"</span><span class="re2">&gt;</span></span>
       <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">"sessionFactory"</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;ref</span> <span class="re0">bean</span>=<span class="st0">"sessionFactory"</span><span class="re2">/&gt;</span></span><span class="sc3"><span class="re1">&lt;/property<span class="re2">&gt;</span></span></span>
  <span class="sc3"><span class="re1">&lt;/bean<span class="re2">&gt;</span></span></span>
<span class="sc3"><span class="re1">&lt;/beans<span class="re2">&gt;</span></span></span>
&nbsp;</pre>
<p>
<p><strong><font size="1">Filter Configuration</font></strong></p>
</p>
<pre class="code"><span class="sc3"><span class="re1">&lt;web</span>-app<span class="re2">&gt;</span></span>
 ...      
  <span class="sc3"><span class="re1">&lt;filter<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;filter</span>-name<span class="re2">&gt;</span></span>hibernateFilter<span class="sc3"><span class="re1">&lt;/filter</span>-name<span class="re2">&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;filter</span>-class<span class="re2">&gt;</span></span>
      org.springframework.orm.hibernate.support.OpenSessionInViewFilter
    <span class="sc3"><span class="re1">&lt;/filter</span>-class<span class="re2">&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;/filter<span class="re2">&gt;</span></span></span>
  ...      
  <span class="sc3"><span class="re1">&lt;filter</span>-mapping<span class="re2">&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;filter</span>-name<span class="re2">&gt;</span></span>hibernateFilter<span class="sc3"><span class="re1">&lt;/filter</span>-name<span class="re2">&gt;</span></span>
     <span class="sc3"><span class="re1">&lt;url</span>-pattern<span class="re2">&gt;</span></span>*.spring<span class="sc3"><span class="re1">&lt;/url</span>-pattern<span class="re2">&gt;</span></span>
  <span class="sc3"><span class="re1">&lt;/filter</span>-mapping<span class="re2">&gt;</span></span>
  ...
<span class="sc3"><span class="re1">&lt;/web</span>-app<span class="re2">&gt;</span></span></pre>
<p>
<p><font size="2">Implementing the Hibernate DAO's to use the open session is simple. In fact, if you are already using the Spring Framework to implement your Hibernate DAO's, most likely you will not have to change a thing. The DAO's must access Hibernate through the convenient HibernateTemplate utility, which makes database access a piece of cake. Below is an example DAO.</font></p>
<p><strong><font size="1">Example DAO</font></font /></strong></p>
</p>
<pre class="code"><span class="kw2">public</span> <span class="kw2">class</span> HibernateProductDAO <span class="kw2">extends</span> HibernateDaoSupport <span class="kw2">implements</span> ProductDAO  <span class="br0">&#123;</span>      
&nbsp;
       <span class="kw2">public</span> Product getProduct<span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AInteger+java.sun.com&bntl=1"><span class="kw3">Integer</span></a> productId<span class="br0">&#41;</span> <span class="br0">&#123;</span>
              <span class="kw2">return</span> <span class="br0">&#40;</span>Product<span class="br0">&#41;</span>getHibernateTemplate<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">load</span><span class="br0">&#40;</span>Product.<span class="me1">class</span>, productId<span class="br0">&#41;</span>;
       <span class="br0">&#125;</span>
&nbsp;
       <span class="kw2">public</span> <a href="http://www.google.com/search?q=allinurl%3AInteger+java.sun.com&bntl=1"><span class="kw3">Integer</span></a> saveProduct<span class="br0">&#40;</span>Product product<span class="br0">&#41;</span> <span class="br0">&#123;</span>
              <span class="kw2">return</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AInteger+java.sun.com&bntl=1"><span class="kw3">Integer</span></a><span class="br0">&#41;</span> getHibernateTemplate<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">save</span><span class="br0">&#40;</span>product<span class="br0">&#41;</span>;
       <span class="br0">&#125;</span>       
&nbsp;
       <span class="kw2">public</span> <span class="kw4">void</span> updateProduct<span class="br0">&#40;</span>Product product<span class="br0">&#41;</span> <span class="br0">&#123;</span>
              getHibernateTemplate<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">update</span><span class="br0">&#40;</span>product<span class="br0">&#41;</span>;
       <span class="br0">&#125;</span>
 <span class="br0">&#125;</span></pre>
<p><p><font size="2"><strong>Being Lazy in the Business Layer</strong> </font></p>
<p><font size="2">Even outside the view, the Spring Framework makes it easy to use lazy load initialization, through the AOP interceptor HibernateInterceptor. The hibernate interceptor transparently intercepts calls to any business object configured in the Spring application context, opening a hibernate session before the call, and closing the session afterward. Let's run through a quick example. Suppose we have an interface BusinessObject:</font> </p>
</p>
<pre class="code"><span class="kw2">public</span> <span class="kw2">interface</span> BusinessObject <span class="br0">&#123;</span> 
     <span class="kw2">public</span> <span class="kw4">void</span> doSomethingThatInvolvesDaos<span class="br0">&#40;</span><span class="br0">&#41;</span>; 
<span class="br0">&#125;</span>&lt;/pre&gt;&lt;p&gt;&lt;font size=<span class="st0">"2"</span>&gt;The <span class="kw2">class</span> BusinessObjectImpl <span class="kw2">implements</span> BusinessObject:&lt;/font&gt;&lt;/p&gt;
&lt;p /&gt;
&lt;pre&gt;public <span class="kw2">class</span> BusinessObjectImpl <span class="kw2">implements</span> BusinessObject <span class="br0">&#123;</span>
    <span class="kw2">public</span> <span class="kw4">void</span> doSomethingThatInvolvesDaos<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="co1">// lots of logic that calls</span>
        <span class="co1">// DAO classes Which access </span>
        <span class="co1">// data objects lazily</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>
<p><p><font size="2">Through some configurations in the Spring application context, we can instruct the HibernateInterceptor to intercept calls to the BusinessObjectImpl allowing it's methods to lazily access data objects. Take a look at the fragment below: </font></p>
</p>
<pre class="code"><span class="sc3"><span class="re1">&lt;beans<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;bean</span> <span class="re0">id</span>=<span class="st0">"hibernateInterceptor"</span> <span class="re0">class</span>=<span class="st0">"org.springframework.orm.hibernate.HibernateInterceptor"</span><span class="re2">&gt;</span></span>
         <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">"sessionFactory"</span><span class="re2">&gt;</span></span>
           <span class="sc3"><span class="re1">&lt;ref</span> <span class="re0">bean</span>=<span class="st0">"sessionFactory"</span><span class="re2">/&gt;</span></span>
         <span class="sc3"><span class="re1">&lt;/property<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;/bean<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;bean</span> <span class="re0">id</span>=<span class="st0">"businessObjectTarget"</span> <span class="re0">class</span>=<span class="st0">"com.acompany.BusinessObjectImpl"</span><span class="re2">&gt;</span></span>
       <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">"someDAO"</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;ref</span> <span class="re0">bean</span>=<span class="st0">"someDAO"</span><span class="re2">/&gt;</span></span><span class="sc3"><span class="re1">&lt;/property<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;/bean<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;bean</span> <span class="re0">id</span>=<span class="st0">"businessObject"</span> <span class="re0">class</span>=<span class="st0">"org.springframework.aop.framework.ProxyFactoryBean"</span><span class="re2">&gt;</span></span>
         <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">"target"</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;ref</span> <span class="re0">bean</span>=<span class="st0">"businessObjectTarget"</span><span class="re2">/&gt;</span></span><span class="sc3"><span class="re1">&lt;/property<span class="re2">&gt;</span></span></span>
         <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">"proxyInterfaces"</span><span class="re2">&gt;</span></span>
           <span class="sc3"><span class="re1">&lt;value<span class="re2">&gt;</span></span></span>com.acompany.BusinessObject<span class="sc3"><span class="re1">&lt;/value<span class="re2">&gt;</span></span></span>
         <span class="sc3"><span class="re1">&lt;/property<span class="re2">&gt;</span></span></span>
         <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">"interceptorNames"</span><span class="re2">&gt;</span></span>
           <span class="sc3"><span class="re1">&lt;list<span class="re2">&gt;</span></span></span>
              <span class="sc3"><span class="re1">&lt;value<span class="re2">&gt;</span></span></span>hibernateInterceptor<span class="sc3"><span class="re1">&lt;/value<span class="re2">&gt;</span></span></span>
           <span class="sc3"><span class="re1">&lt;/list<span class="re2">&gt;</span></span></span>
         <span class="sc3"><span class="re1">&lt;/property<span class="re2">&gt;</span></span></span>
     <span class="sc3"><span class="re1">&lt;/bean<span class="re2">&gt;</span></span></span>            
<span class="sc3"><span class="re1">&lt;/beans<span class="re2">&gt;</span></span></span>
&nbsp;
&nbsp;</pre>
<p>
<p><font size="2">When the businessObject bean is referenced, the HibernateInterceptor opens a hibernate session and passes the call onto the BusinessObjectImpl. When the BusinessObjectImpl has finished executing, the HibernateInterceptor transparently closes the session. The application code has no knowledge of any persistence logic, yet it is still able to lazily access data objects.</font></p>
<p><font size="2"><strong>Being Lazy in your Unit Tests</strong><p><font size="2">Last but not least, we'll need the ability to test our lazy application from J-Unit. This is easily done by overriding the setUp and tearDown methods of the TestCase class. I prefer to keep this code in a convenient abstract TestCase class for all of my tests to extend.</font></p>
</p>
<pre class="code"><span class="kw2">public</span> abstract <span class="kw2">class</span> MyLazyTestCase <span class="kw2">extends</span> TestCase <span class="br0">&#123;</span>
&nbsp;
        <span class="kw2">private</span> SessionFactory sessionFactory;
        <span class="kw2">private</span> Session session;
	
        <span class="kw2">public</span> <span class="kw4">void</span> setUp<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw2">throws</span> <a href="http://www.google.com/search?q=allinurl%3AException+java.sun.com&bntl=1"><span class="kw3">Exception</span></a> <span class="br0">&#123;</span>
	    super.<span class="me1">setUp</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
	    SessionFactory sessionFactory = <span class="br0">&#40;</span>SessionFactory<span class="br0">&#41;</span> getBean<span class="br0">&#40;</span>\<span class="st0">"sessionFactory&amp;quot&lt;img alt="</span>;<span class="br0">&#41;</span><span class="st0">" src="</span>http:<span class="co1">//www.dflying.net/plugins/smileys/icons/default/wink_smile.gif&quot; /&gt;;</span>
	    session = SessionFactoryUtils.<span class="me1">getSession</span><span class="br0">&#40;</span>sessionFactory, <span class="kw2">true</span><span class="br0">&#41;</span>;
	    Session s = sessionFactory.<span class="me1">openSession</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
	    TransactionSynchronizationManager.<span class="me1">bindResource</span><span class="br0">&#40;</span>sessionFactory, <span class="kw2">new</span> SessionHolder<span class="br0">&#40;</span>s<span class="br0">&#41;</span><span class="br0">&#41;</span>;
&nbsp;
        <span class="br0">&#125;</span>
&nbsp;
        <span class="kw2">protected</span> <a href="http://www.google.com/search?q=allinurl%3AObject+java.sun.com&bntl=1"><span class="kw3">Object</span></a> getBean<span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&bntl=1"><span class="kw3">String</span></a> beanName<span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="co1">//Code to get objects from Spring application context</span>
        <span class="br0">&#125;</span>
	
        <span class="kw2">public</span> <span class="kw4">void</span> tearDown<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw2">throws</span> <a href="http://www.google.com/search?q=allinurl%3AException+java.sun.com&bntl=1"><span class="kw3">Exception</span></a> <span class="br0">&#123;</span>
	    super.<span class="me1">tearDown</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
	    SessionHolder holder = <span class="br0">&#40;</span>SessionHolder<span class="br0">&#41;</span> TransactionSynchronizationManager.<span class="me1">getResource</span><span class="br0">&#40;</span>sessionFactory<span class="br0">&#41;</span>;
	    Session s = holder.<span class="me1">getSession</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; 
	    s.<span class="me1">flush</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
	    TransactionSynchronizationManager.<span class="me1">unbindResource</span><span class="br0">&#40;</span>sessionFactory<span class="br0">&#41;</span>;
	    SessionFactoryUtils.<span class="me1">closeSessionIfNecessary</span><span class="br0">&#40;</span>s, sessionFactory<span class="br0">&#41;</span>;
        <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>
<p>
</p>
   <br>文章来源:<a href='http://blueoxygen.dflying.net/3/archive/84_hibernate_performance_tuning.html'>http://blueoxygen.dflying.net/3/archive/84_hibernate_performance_tuning.html</a><img src ="http://www.blogjava.net/blueoxygen/aggbug/35579.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/blueoxygen/" target="_blank">BlueO2</a> 2006-03-16 11:19 <a href="http://www.blogjava.net/blueoxygen/archive/2006/03/16/35579.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>