<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> <base href="https://hibernate.atlassian.net" /> 
        <title>Message Title</title> 
    </head> 
    <body class="jira" style="color: #333; font-family: Arial, sans-serif; font-size: 14px; line-height: 1.429"> 
        <table id="background-table" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f5f5f5; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
            <!-- header here --> 
            <tr> 
                <td id="header-pattern-container" style="padding: 0px; border-collapse: collapse; padding: 10px 20px"> 
                    <table id="header-pattern" cellspacing="0" cellpadding="0" border="0" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                        <tr> 
                            <td id="header-avatar-image-container" valign="top" style="padding: 0px; border-collapse: collapse; vertical-align: top; width: 32px; padding-right: 8px"> <img id="header-avatar-image" class="image_fix" src="https://secure.gravatar.com/avatar/20ca57662096a6ea79a466ad9efab45d?d=mm&amp;s=48" height="32" width="32" border="0" style="border-radius: 3px; vertical-align: top" /> 
                            </td> 
                            <td id="header-text-container" valign="middle" style="padding: 0px; border-collapse: collapse; vertical-align: middle; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 1px"> <a class="user-hover" rel="jkronegg" id="email_jkronegg" href="https://hibernate.atlassian.net/secure/ViewProfile.jspa?name=jkronegg" style="color:#6c797f;; color: #3b73af; text-decoration: none">Julien Kronegg</a> <strong>commented</strong> on <a href="https://hibernate.atlassian.net/browse/HHH-1523" style="color: #3b73af; text-decoration: none"><img src="cid:jira-generated-image-static-newfeature-be6294b9-a3e9-4ead-97c4-edd666587e12" height="16" width="16" border="0" align="absmiddle" alt="New Feature" /> HHH-1523</a> 
                            </td> 
                        </tr> 
                    </table> 
                </td> 
            </tr> 
            <tr> 
                <td id="email-content-container" style="padding: 0px; border-collapse: collapse; padding: 0 20px"> 
                    <table id="email-content-table" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-spacing: 0; border-collapse: separate"> 
                        <tr> 
                            <!-- there needs to be content in the cell for it to render in some clients --> 
                            <td class="email-content-rounded-top mobile-expand" style="padding: 0px; border-collapse: collapse; color: #fff; padding: 0 15px 0 16px; height: 15px; background-color: #fff; border-left: 1px solid #ccc; border-top: 1px solid #ccc; border-right: 1px solid #ccc; border-bottom: 0; border-top-right-radius: 5px; border-top-left-radius: 5px; height: 10px; line-height: 10px; padding: 0 15px 0 16px; mso-line-height-rule: exactly">
                                &nbsp;
                            </td> 
                        </tr> 
                        <tr> 
                            <td class="email-content-main mobile-expand " style="padding: 0px; border-collapse: collapse; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: 0; border-bottom: 0; padding: 0 15px 0 16px; background-color: #fff"> 
                                <table class="page-title-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                                    <tr> 
                                        <td style="vertical-align: top;; padding: 0px; border-collapse: collapse; padding-right: 5px; font-size: 20px; line-height: 30px; mso-line-height-rule: exactly" class="page-title-pattern-header-container"> <span class="page-title-pattern-header" style="font-family: Arial, sans-serif; padding: 0; font-size: 20px; line-height: 30px; mso-text-raise: 2px; mso-line-height-rule: exactly; vertical-align: middle"> <a href="https://hibernate.atlassian.net/browse/HHH-1523" style="color: #3b73af; text-decoration: none">Re: Rebuild fetches from query-cache hits</a> </span> 
                                        </td> 
                                    </tr> 
                                </table> 
                            </td> 
                        </tr> 
                        <tr> 
                            <td id="text-paragraph-pattern-top" class="email-content-main mobile-expand  comment-top-pattern" style="padding: 0px; border-collapse: collapse; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: 0; border-bottom: 0; padding: 0 15px 0 16px; background-color: #fff; border-bottom: none; padding-bottom: 0"> 
                                <table class="text-paragraph-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 2px"> 
                                    <tr> 
                                        <td class="text-paragraph-pattern-container mobile-resize-text " style="padding: 0px; border-collapse: collapse; padding: 0 0 10px 0"> 
                                            <p style="margin: 10px 0 0 0">@Steve, @Erkki: <br /> I finaly found some time to experiment further on this issue. I'm using a variant of the query and test case described in <a href="https://hibernate.atlassian.net/browse/HHH-1523?focusedCommentId=44300&amp;page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-44300" class="external-link" rel="nofollow" style="color: #3b73af; text-decoration: none">my post from 11/nov./2011 7:07 PM</a>:</p> 
                                            <div class="code panel" style="border-width: 1px;; border: 1px solid #ccc; background: #f5f5f5; font-size: 12px; line-height: 1.333; font-family: monospace; border: 1px solid #ccc; -moz-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; margin: 9px 0">
                                                <div class="codeContent panelContent" style="padding: 9px 12px"> 
                                                    <pre class="code-java" style="margin: 10px 0 0 0; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal">
SELECT dep.employees FROM Department dep
</pre> 
                                                </div>
                                            </div> 
                                            <p style="margin: 10px 0 0 0">Neither the <tt>Employee</tt> nor the <tt>Department</tt> JPA entities are cached in L2, however the query above is cached.</p> 
                                            <p style="margin: 10px 0 0 0">Then I run the test case:</p> 
                                            <div class="code panel" style="border-width: 1px;; border: 1px solid #ccc; background: #f5f5f5; font-size: 12px; line-height: 1.333; font-family: monospace; border: 1px solid #ccc; -moz-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; margin: 9px 0">
                                                <div class="codeContent panelContent" style="padding: 9px 12px"> 
                                                    <pre class="code-java" style="margin: 10px 0 0 0; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal">
<span class="code-comment" style="color: #808080">// step 1
</span>log.info(<span class="code-quote" style="color: #009100">&quot;============== step 1 ================&quot;</span>);
EntityManager em = ... <span class="code-comment" style="color: #808080">// build an EM from the EMF
</span>Query q = em.createQuery(<span class="code-quote" style="color: #009100">&quot;SELECT dep.employees FROM Department dep&quot;</span>);
... <span class="code-comment" style="color: #808080">// enable query cache <span class="code-keyword" style="color: #000091; color: #808080">for</span> q
</span>List&lt;Employee&gt; list = q.getResultList();
em.close();
list.iterator().next().getId(); <span class="code-comment" style="color: #808080">// no LazyInitializationException nor NullPointerException raised here (expected result)
</span>
<span class="code-comment" style="color: #808080">// step 2
</span>log.info(<span class="code-quote" style="color: #009100">&quot;============== step 2 ================&quot;</span>);
EntityManager em = ... <span class="code-comment" style="color: #808080">// build an EM from the EMF
</span>Query q = em.createQuery(<span class="code-quote" style="color: #009100">&quot;SELECT dep.employees FROM Department dep&quot;</span>);
... <span class="code-comment" style="color: #808080">// enable query cache <span class="code-keyword" style="color: #000091; color: #808080">for</span> q
</span>List&lt;Employee&gt; list = q.getResultList();
em.close();
list.iterator().next().getId(); <span class="code-comment" style="color: #808080">// NullPointerException raised here!!! (unexpected result)</span>
</pre> 
                                                </div>
                                            </div> 
                                            <p style="margin: 10px 0 0 0">Digging into the <tt>org.hibernate.cache.StandardQueryCache</tt>, it appears that during the first step, the <tt>StandardQueryCache.put(QueryKey key, Type[] returnTypes, List result, boolean isNaturalKeyLookup, SessionImplementor session)</tt> method is called with a <tt>returnTypes=[org.hibernate.type.SetType(Employee)]</tt>. The <tt>SetType.disassemble(value,session,owner)</tt> method is used to provide a cacheable representation of the <tt>List&lt;Employee&gt;</tt>. However, the <tt>SetType.disassemble()</tt> method always returns null because the provided <tt>owner</tt> is null. Consequently, the <tt>cacheRegion</tt> is updated with a <tt>cacheable</tt> as an <tt>ArrayList</tt> containing a timestamp and <tt>result.size()</tt> null values (instead of the <tt>Employee.id</tt> for each List item).</p> 
                                            <p style="margin: 10px 0 0 0">During the 2nd step, the <tt>StandardQueryCache.get(QueryKey key, Type[] returnTypes, boolean isNaturalKeyLookup, Set spaces, SessionImplementor session)</tt> method is called because the query is cached. The cached values are obtained as <tt>List cacheable = (List)cacheRegion.get(key)</tt>. In our case, this list contains the timestamp and the null values. Reassembling the List values lead to a List of null elements instead of a <tt>List&lt;Employee&gt;</tt>. Consequently, the <tt>list.iterator().next().getId();</tt> in the 2nd step raises a <tt>NullPointerException</tt>.</p> 
                                            <p style="margin: 10px 0 0 0">The cause may be either:</p> 
                                            <ul> 
                                                <li>
                                                    the <tt>SetType</tt> is not capable to assemble/disassemble the data when used for by the <tt>StandardQueryCache</tt> (it's a design issue)
                                                </li> 
                                                <li>
                                                    the <tt>StandardQueryCache</tt> is not called with the correct <tt>returnTypes</tt> (it's a bug)
                                                </li> 
                                            </ul> 
                                            <p style="margin: 10px 0 0 0">As a workaround, I've created the following <tt>MyQueryCache</tt> which extends the <tt>StandardQueryCache</tt> as follow:</p> 
                                            <div class="code panel" style="border-width: 1px;; border: 1px solid #ccc; background: #f5f5f5; font-size: 12px; line-height: 1.333; font-family: monospace; border: 1px solid #ccc; -moz-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; margin: 9px 0">
                                                <div class="codeContent panelContent" style="padding: 9px 12px"> 
                                                    <pre class="code-java" style="margin: 10px 0 0 0; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal">
<span class="code-keyword" style="color: #000091">public</span> class MyQueryCache <span class="code-keyword" style="color: #000091">extends</span> StandardQueryCache {
 
  <span class="code-keyword" style="color: #000091">public</span> MyQueryCache(Settings settings, Properties props, UpdateTimestampsCache updateTimestampsCache, <span class="code-object" style="color: #910091">String</span> regionName)
        <span class="code-keyword" style="color: #000091">throws</span> HibernateException {
    <span class="code-keyword" style="color: #000091">super</span>(settings, props, updateTimestampsCache, regionName);
  }
 
  @Override
  <span class="code-keyword" style="color: #000091">public</span> <span class="code-object" style="color: #910091">boolean</span> put(QueryKey key, Type[] returnTypes, List result,
        <span class="code-object" style="color: #910091">boolean</span> isNaturalKeyLookup, SessionImplementor session)
        <span class="code-keyword" style="color: #000091">throws</span> HibernateException {
    <span class="code-keyword" style="color: #000091">return</span> <span class="code-keyword" style="color: #000091">super</span>.put(key, getCorrectedReturnTypes(returnTypes, session), result, isNaturalKeyLookup, session);
  }
 
  @Override
  <span class="code-keyword" style="color: #000091">public</span> List get(QueryKey key, Type[] returnTypes,
        <span class="code-object" style="color: #910091">boolean</span> isNaturalKeyLookup, Set spaces, SessionImplementor session)
        <span class="code-keyword" style="color: #000091">throws</span> HibernateException {
    <span class="code-keyword" style="color: #000091">return</span> <span class="code-keyword" style="color: #000091">super</span>.get(key, getCorrectedReturnTypes(returnTypes, session), isNaturalKeyLookup, spaces, session);
  }
 
  <span class="code-keyword" style="color: #000091">private</span> Type[] getCorrectedReturnTypes(Type[] returnTypes, SessionImplementor session) {
    Type[] returnTypesNew = returnTypes;
    <span class="code-keyword" style="color: #000091">if</span> ( returnTypes.length == 1 ) {
      Type type = returnTypes[0];
      <span class="code-keyword" style="color: #000091">if</span> (type <span class="code-keyword" style="color: #000091">instanceof</span> SetType) {
        <span class="code-object" style="color: #910091">String</span> entityClassName = ((SetType) type).getElementType(session.getFactory()).getName();
        returnTypesNew[0] = <span class="code-keyword" style="color: #000091">new</span> ManyToOneType(entityClassName);
      }
    }
    <span class="code-keyword" style="color: #000091">return</span> returnTypesNew;
  }
}
</pre> 
                                                </div>
                                            </div> 
                                            <p style="margin: 10px 0 0 0">Basically, this custom query cache implementation replaces the <tt>SetType</tt> of the <tt>returnTypes</tt> by the (supposely equivalent) <tt>ManyToOneType</tt>. I also created the adhoc query cache factory (a copy of <tt>StandardQueryCacheFactory</tt> which returns a <tt>MyQueryCache</tt> instaqnce), and configured the <tt>persistence.xml</tt> by adding a <tt>&lt;property name=&quot;hibernate.cache.query_cache_factory&quot; value=&quot;my.testpackage.MyQueryCacheFactory&quot; /&gt;</tt>.</p> 
                                            <p style="margin: 10px 0 0 0">Using this custom query cache implementation, the final result is the same when running the first and second steps. However, the behavior is not the same due to the query cache behavior (one query with INNER JOIN for the first step and two simple query for the second step):</p> 
                                            <div class="code panel" style="border-width: 1px;; border: 1px solid #ccc; background: #f5f5f5; font-size: 12px; line-height: 1.333; font-family: monospace; border: 1px solid #ccc; -moz-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; margin: 9px 0">
                                                <div class="codeContent panelContent" style="padding: 9px 12px"> 
                                                    <pre class="code-java" style="margin: 10px 0 0 0; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal">
INFO: ============== step 1 ================
Hibernate: select [..employee fields removed <span class="code-keyword" style="color: #000091">for</span> brevity..] from CACHE_ISSUE_EMP employee0_ <span class="code-keyword" style="color: #000091">inner</span> join CACHE_ISSUE_DEP department1_ on employee0_.DEPARTMENT_ID=department1_.DEPARTMENT_ID
INFO: ============== step 2 ================
Hibernate: select [..employee fields removed <span class="code-keyword" style="color: #000091">for</span> brevity...] from CACHE_ISSUE_EMP employee0_ where employee0_.EMP_ID=?
Hibernate: select [..employee fields removed <span class="code-keyword" style="color: #000091">for</span> brevity...] from CACHE_ISSUE_EMP employee0_ where employee0_.EMP_ID=?
</pre> 
                                                </div>
                                            </div> 
                                            <p style="margin: 10px 0 0 0">The great thing about this workaround is that it does not require to change the Hibernate version. This should match your expectations, Erkki.</p> 
                                            <p style="margin: 10px 0 0 0">Of course, with this simple example, the query cache efficient is not evident since we replace one query by two queries. But this is only a test case.</p> 
                                            <p style="margin: 10px 0 0 0">For reference, I used : Hibernate 3.3.1 (but the <tt>StandardQueryCache</tt> is very similar other Hibernate versions such as in 4.3.5), EhCache 2.4.3, DB2.</p> 
                                        </td> 
                                    </tr> 
                                </table> 
                            </td> 
                        </tr> 
                        <tr> 
                            <td class="email-content-main mobile-expand " style="padding: 0px; border-collapse: collapse; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: 0; border-bottom: 0; padding: 0 15px 0 16px; background-color: #fff"> 
                                <table id="actions-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 1px"> 
                                    <tr> 
                                        <td id="actions-pattern-container" valign="middle" style="padding: 0px; border-collapse: collapse; padding: 10px 0 10px 24px; vertical-align: middle; padding-left: 0"> 
                                            <table align="left" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                                                <tr> 
                                                    <td class="actions-pattern-action-icon-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 0px; vertical-align: middle"> <a href="https://hibernate.atlassian.net/browse/HHH-1523#add-comment" target="_blank" title="Add Comment" style="color: #3b73af; text-decoration: none"> <img class="actions-pattern-action-icon-image" src="cid:jira-generated-image-static-comment-icon-98811f2d-b080-41ca-b272-826b4aa7a95e" alt="Add Comment" title="Add Comment" height="16" width="16" border="0" style="vertical-align: middle" /> </a> 
                                                    </td> 
                                                    <td class="actions-pattern-action-text-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 4px; padding-left: 5px"> <a href="https://hibernate.atlassian.net/browse/HHH-1523#add-comment" target="_blank" title="Add Comment" style="color: #3b73af; text-decoration: none">Add Comment</a> 
                                                    </td> 
                                                </tr> 
                                            </table> 
                                        </td> 
                                    </tr> 
                                </table> 
                            </td> 
                        </tr> 
                        <!-- there needs to be content in the cell for it to render in some clients --> 
                        <tr> 
                            <td class="email-content-rounded-bottom mobile-expand" style="padding: 0px; border-collapse: collapse; color: #fff; padding: 0 15px 0 16px; height: 5px; line-height: 5px; background-color: #fff; border-top: 0; border-left: 1px solid #ccc; border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; mso-line-height-rule: exactly">
                                &nbsp;
                            </td> 
                        </tr> 
                    </table> 
                </td> 
            </tr> 
            <tr> 
                <td id="footer-pattern" style="padding: 0px; border-collapse: collapse; padding: 12px 20px"> 
                    <table id="footer-pattern-container" cellspacing="0" cellpadding="0" border="0" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                        <tr> 
                            <td id="footer-pattern-text" class="mobile-resize-text" width="100%" style="padding: 0px; border-collapse: collapse; color: #999; font-size: 12px; line-height: 18px; font-family: Arial, sans-serif; mso-line-height-rule: exactly; mso-text-raise: 2px">
                                 This message was sent by Atlassian JIRA <span id="footer-build-information">(v6.4-OD-04-006#64001-<span title="b1633a7e36a916f95ac968aafe0f8b849ce804e3" data-commit-id="b1633a7e36a916f95ac968aafe0f8b849ce804e3}">sha1:b1633a7</span>)</span> 
                            </td> 
                            <td id="footer-pattern-logo-desktop-container" valign="top" style="padding: 0px; border-collapse: collapse; padding-left: 20px; vertical-align: top"> 
                                <table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                                    <tr> 
                                        <td id="footer-pattern-logo-desktop-padding" style="padding: 0px; border-collapse: collapse; padding-top: 3px"> <img id="footer-pattern-logo-desktop" src="cid:jira-generated-image-static-footer-desktop-logo-b3c02449-1da5-473d-a730-604c9c8b7a81" alt="Atlassian logo" title="Atlassian logo" width="169" height="36" class="image_fix" /> 
                                        </td> 
                                    </tr> 
                                </table> 
                            </td> 
                        </tr> 
                    </table> 
                </td> 
            </tr> 
        </table>   
    </body>
</html>