{"id":620,"date":"2013-03-26T15:47:18","date_gmt":"2013-03-26T22:47:18","guid":{"rendered":"http:\/\/10kdev.ivystreetinc.com\/?p=620"},"modified":"2013-03-27T09:46:40","modified_gmt":"2013-03-27T16:46:40","slug":"hibernate-eager-fetch-gets-too-many-results","status":"publish","type":"post","link":"http:\/\/10kdev.net\/?p=620","title":{"rendered":"Hibernate Eager Fetch gets Too Many Results"},"content":{"rendered":"<p>Working on a bug today, there was a list of items with a set of sub items coming back from the database via Hibernate. Something like this in pseudocode:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n@Entity\r\n@Table(name = &quot;PARENT&quot;, schema = &quot;USER&quot;)\r\npublic class Parent implements Serializable {\r\n\r\nprivate Long id;\r\nprivate String name;\r\nprivate List&lt;Child&gt; childList = new ArrayList&lt;Child&gt;();\r\n\r\n@Id\r\n@SequenceGenerator\r\n@Column(name=&quot;PARENT_ID&quot;)\r\npublic Long getId() {\r\nreturn id;\r\n}\r\n\r\npublic void setId(Long id) {\r\nthis.id = id;\r\n}\r\n\r\n@Id\r\n@Column\r\npublic String getName() {\r\nreturn name;\r\n}\r\n\r\npublic void setName(String name) {\r\nthis.name = name;\r\n}\r\n\r\n@OneToMany(mappedBy = &quot;parent&quot;,fetch = FetchType.EAGER)\r\n@Cascade(CascadeType.ALL)\r\npublic List&lt;Child&gt; getChildList() {\r\nreturn childList;\r\n}\r\n\r\npublic void setChildList(List&lt;Child&gt; childList) {\r\nthis.childList = childList;\r\n}\r\n}\r\n\r\n@Entity\r\n@Table(name = &quot;CHILD&quot;, schema = &quot;USER&quot;)\r\npublic class Child implements Serializable {\r\n\r\nprivate Long id;\r\nprivate String name;\r\nprivate Parent parent;\r\n\r\n@Id\r\n@SequenceGenerator\r\n@Column(name=&quot;CHILD_ID&quot;)\r\npublic Long getId() {\r\nreturn id;\r\n}\r\n\r\npublic void setId(Long id) {\r\nthis.id = id;\r\n}\r\n\r\n@Id\r\n@Column\r\npublic String getName() {\r\nreturn name;\r\n}\r\n\r\npublic void setName(String name) {\r\nthis.name = name;\r\n}\r\n\r\n@ManyToOne\r\n@JoinColumn(name = &quot;PARENT_ID&quot;)\r\npublic Parent getParent() {\r\nreturn parent;\r\n}\r\n\r\npublic void setParent(Parent parent) {\r\nthis.parent = parent;\r\n}\r\n}\r\n\r\n@Repository\r\npublic class ParentDao implements SomeGenericDao {\r\n\r\npublic List&lt;JasperReportTemplate&gt; getAllActiveTemplates(Long firmId) {\r\nfinal Criteria criteria = getCurrentSession()\r\n       .createCriteria(getModelClass())\r\n       .(DO SOME CRITERIA ETC&gt;);\r\nreturn criteria.list();\r\n}\r\n}\r\n<\/pre>\n<p>Here are your data sets for PARENT(parent_id, name):<\/p>\n<ul>\n<li>(1,&#8221;parent1&#8243;)<\/li>\n<li>(2,&#8221;parent2&#8243;)<\/li>\n<\/ul>\n<p>And your data sets for CHILD(child_id,parent_id(foreign key),name)<\/p>\n<ul>\n<li>(1,1,&#8221;child1&#8243;)<\/li>\n<li>(2,1,&#8221;child2&#8243;)<\/li>\n<li>(3,2,&#8221;child3&#8243;)<\/li>\n<li>(4,2,&#8221;child4&#8243;)<\/li>\n<\/ul>\n<p>When you try to make a list of *just* PARENT with this configuration you end up getting:<\/p>\n<ol>\n<li>parent1<\/li>\n<li>parent1<\/li>\n<li>parent2<\/li>\n<li>parent2<\/li>\n<\/ol>\n<p>But what you want is this:<\/p>\n<ol>\n<li>parent1<\/li>\n<li>parent2<\/li>\n<\/ol>\n<p>It&#8217;s because of that EAGER fetch &#8212; it forces everything to be in ONE BIG QUERY with all the tables so you get a Cartesian result. What you really want is just unique PARENT values.<\/p>\n<p><strong>Solutions<\/strong><\/p>\n<p><strong>Removing &#8220;EAGER&#8221;<\/strong><\/p>\n<p>First, if you remove the EAGER, you won&#8217;t be loading any CHILD data. This could be problematic because the CHILD data won&#8217;t be available without making another data call to hydrate those objects. Depends on what you want.<\/p>\n<p><strong>Returning a Set instead of a List from the DAO<\/strong><\/p>\n<p>Another solution is something like this in the DAO in your java, that will return a set object that automatically filters the unique objects:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n Set = new LinkedHashSet();\r\n set.addAll(criteria.list());\r\n return set;\r\n<\/pre>\n<p>Supposably this is a workaround. it does work though.<\/p>\n<p><strong>Setting @Fetch<\/strong><\/p>\n<p>yet another solution, and one that I use, is to just set @Fetch on the child property:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n @OneToMany(mappedBy = &quot;parent&quot;,fetch = FetchType.EAGER)\r\n @Cascade(CascadeType.ALL)\r\n @Fetch(FetchMode.SUBSELECT)\r\n public List&lt;Child&gt; getChildList() {\r\n return childList;\r\n }\r\n<\/pre>\n<p>I&#8217;ve also had success with using FetchMode.SELECT. This forces Hibernate to do a subquery on the child instead of one massive query &#8212; and you get all the data back.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Working on a bug today, there was a list of items with a set of sub items coming back from the database via Hibernate. Something like this in pseudocode: Here are your data sets for PARENT(parent_id, name): (1,&#8221;parent1&#8243;) (2,&#8221;parent2&#8243;) And your data sets for CHILD(child_id,parent_id(foreign key),name) (1,1,&#8221;child1&#8243;) (2,1,&#8221;child2&#8243;) (3,2,&#8221;child3&#8243;) (4,2,&#8221;child4&#8243;) When you try to make [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/10kdev.net\/index.php?rest_route=\/wp\/v2\/posts\/620"}],"collection":[{"href":"http:\/\/10kdev.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/10kdev.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/10kdev.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/10kdev.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=620"}],"version-history":[{"count":15,"href":"http:\/\/10kdev.net\/index.php?rest_route=\/wp\/v2\/posts\/620\/revisions"}],"predecessor-version":[{"id":634,"href":"http:\/\/10kdev.net\/index.php?rest_route=\/wp\/v2\/posts\/620\/revisions\/634"}],"wp:attachment":[{"href":"http:\/\/10kdev.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=620"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/10kdev.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=620"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/10kdev.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=620"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}