{"id":100,"date":"2009-08-26T12:40:00","date_gmt":"2009-08-26T12:40:00","guid":{"rendered":"http:\/\/www.gmarwaha.com\/blog\/?p=100"},"modified":"2014-09-14T05:15:17","modified_gmt":"2014-09-14T05:15:17","slug":"hibernate-why-should-i-force-discriminator","status":"publish","type":"post","link":"https:\/\/www.gmarwaha.com\/blog\/2009\/08\/26\/hibernate-why-should-i-force-discriminator\/","title":{"rendered":"Hibernate: Why should I Force Discriminator?"},"content":{"rendered":"<p>Hibernate is an ambitious project that aims to be a complete solution to the problem of managing persistent data in java. Even with such an arduous task before them, the hibernate team tries very hard to expose a simple API for developers like us. Still, the complexity behind the API shows its ugly face time and again and I believe it is unavoidable as long as the mismatch between Object and Relational world exists.<\/p>\n<p>That said, although I have worked with hibernate for many years and have been its advocate in all my organizations, I keep facing newer issues and keep finding newer ways to work with it efficiently and effectively. Recently, when I was working for <a href=\"http:\/\/www.nboomi.com\">nboomi.com<\/a>, I faced an issue when mapping a <em>OneToMany<\/em> relationship to the sub-classes of <em>&#8220;Single Table Inheritance&#8221;<\/em> strategy. After a frustrating couple of hours of debugging I finally landed on the correct solution. So, I thought other developers who will travel this path could get benefited and started writing this blog post.<\/p>\n<p>Let me explain the issue I faced with an example. Assume you have a normal <em>User<\/em> Entity with the typical <em>id<\/em>, <em>version<\/em> and <em>loginId<\/em> properties. Assume this <em>User<\/em> can have many <em>AboutUs<\/em> sections and many <em>Service<\/em> sections. You don&#8217;t need to be an architect to model them as <em>OneToMany<\/em> relationships from <em>User<\/em>. So, I modelled <em>UserAboutSection<\/em> and <em>UserServiceSection<\/em> entities and created a <em>OneToMany<\/em> relationship between <em>User<\/em> and these entities. Looking at the commonality between these two, I decided to factor out the common fields into a superclass called <em>UserSection<\/em>. Now, both <em>UserAboutSection<\/em> and <em>UserServiceSection<\/em> extends <em>UserSection<\/em>. I chose to map this Inheritance hierarchy using &#8220;Single Table Inheritance&#8221; strategy to keep it simple and since most of the fields were common and only a few were specific. <\/p>\n<p>The <em>User<\/em> entity is given below. Notice the <em>List&lt;UserAboutSection&gt;<\/em> and a <em>List&lt;UserServiceSection&gt;<\/em> mapped using <em>OneToMany<\/em> relationship.<\/p>\n<p>The getters, setters, adders, imports and static imports are omitted for brevity.<\/p>\n<pre class=\"prettyprint\">\r\n@Entity @Table(name = \"user\")\r\npublic class User extends BaseEntity {\r\n\r\n    @Column(name = \"login_id\")\r\n    private String loginId;\r\n\r\n    @Column(name = \"password\")\r\n    private String password;\r\n\r\n    ...\r\n\r\n    @OneToMany(cascade = {CascadeType.ALL})\r\n    @JoinColumn(name = \"user_id\", nullable = false)\r\n    @IndexColumn(name = \"user_section_position\")\r\n    List&lt;UserAboutSection&gt; aboutUs;\r\n\r\n    @OneToMany(cascade = {CascadeType.ALL})\r\n    @JoinColumn(name = \"user_id\", nullable = false)\r\n    @IndexColumn(name = \"user_section_position\")\r\n    List&lt;UserServiceSection&gt; services;\r\n\r\n    ... Getters, Setters and Adders\r\n}\r\n<\/pre>\n<p>Here goes the <em>UserSection<\/em> entity that acts as the base class in this &#8220;Single Table Inheritance&#8221; strategy. Hibernate uses the @DiscriminatorColumn annotation to distinguish between sub-classes. <\/p>\n<pre class=\"prettyprint\">\r\n@Entity @Table(name = \"user_section\")\r\n@Inheritance(strategy= InheritanceType.SINGLE_TABLE)\r\n@DiscriminatorColumn(name=\"user_section_type\", discriminatorType = STRING) \r\npublic class UserSection extends BaseEntity {\r\n    \r\n    @Column(name = \"title\")         \r\n    protected String title;\r\n\r\n    @Column(name = \"description\")   \r\n    protected String description;\r\n\r\n    ... Getters and Setters\r\n}\r\n<\/pre>\n<p>Here goes the <em>UserAboutSection<\/em> entity that derives from the <em>UserSection<\/em> entity. Hibernate uses the @DiscriminatorValue annotation to decide if a row in the database belongs to an instance of this class.<\/p>\n<pre class=\"prettyprint\">\r\n@Entity @DiscriminatorValue(\"ABOUT\")\r\npublic class UserAboutSection extends UserSection {\r\n    @ManyToOne \r\n    @JoinColumn(name=\"user_id\",updatable=false,insertable=false,nullable=false)\r\n    protected User user;\r\n\r\n    ... Other Properties specific to UserAboutSection\r\n}\r\n<\/pre>\n<p>Here goes the <em>UserServiceSection<\/em> entity that derives from the <em>UserSection<\/em> entity. Hibernate uses the @DiscriminatorValue annotation to decide if a row in the database belongs to an instance of this class.<\/p>\n<pre class=\"prettyprint\">\r\n@Entity @DiscriminatorValue(\"SERVICE\")\r\npublic class UserServiceSection extends UserSection {\r\n    @ManyToOne \r\n    @JoinColumn(name=\"user_id\",updatable=false,insertable=false,nullable=false)\r\n    protected User user;\r\n\r\n    ... Other Properties specific to UserServiceSection\r\n}\r\n<\/pre>\n<p>Pretty straightforward&#8230; huh! When you try to retrieve an instance of <em>User<\/em> along with its <em>aboutUs<\/em> and <em>services<\/em> collections eagerly (or lazily &#8211; doesn&#8217;t matter), what do you expect? <\/p>\n<p>I expected an instance of <em>User<\/em> with the <em>aboutUs<\/em> collection filled with only <em>UserAboutSection<\/em> instances and the <em>services<\/em> collection filled with only <em>UserServiceSection<\/em> instances corresponding to only the rows they represent in the database. And I believe this expectation is valid, because that is what the mapping looks like and hibernate also has all the information it needs to make this work. <\/p>\n<p>But I got something different. Both the <em>aboutUs<\/em> and <em>services<\/em> collections had all the <em>UserSection<\/em> rows that belong to this <em>User<\/em>. I mean, <em>aboutUs<\/em> collection had all the <em>UserSection<\/em> instances including U<em>serAboutSection<\/em> and <em>UserServiceSection<\/em> instances. This was surprising because hibernate has all the information it needs to populate the right instances. <\/p>\n<p>After quite a bit of debugging, googling and RTFM-ing I landed upon <em>@ForceDiscriminator<\/em> annotation. This annotation has to be applied to the base class in the Inheritance hierarchy for &#8220;Single Table Inheritance&#8221; strategy. In my case, I had to apply it to <em>UserSection<\/em> entity. The <em>UserSection<\/em> entity after applying this annotation is given below&#8230; <\/p>\n<pre class=\"prettyprint\">\r\n@Entity @Table(name = \"user_section\")\r\n@Inheritance(strategy= InheritanceType.SINGLE_TABLE)\r\n@DiscriminatorColumn(name=\"user_section_type\", discriminatorType = STRING) \r\n@ForceDiscriminator\r\npublic class UserSection extends BaseEntity {\r\n    \r\n    @Column(name = \"title\")         \r\n    protected String title;\r\n\r\n    @Column(name = \"description\")   \r\n    protected String description;\r\n\r\n    ... Getters and Setters\r\n}\r\n<\/pre>\n<p>Once I ask hibernate to Force Discriminiator, it is happy and populates the aboutUs and services collections with its respective instances. <\/p>\n<p>Ok, Problem Solved! But why did I have to tell hibernate to Force Discriminator. Shouldn&#8217;t that be the default behaviour. Is it a bug in hibernate or is it a feature? Am I missing something? If any one of you hibernate fans have walked this path and know the answer, please feel free to drop in a comment. I sincerely hope this post will be a valuable time-saver for other hibernate developers who step on this Bug\/Feature. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hibernate is an ambitious project that aims to be a complete solution to the problem of managing persistent data in java. Even with such an arduous task before them, the hibernate team tries very hard to expose a simple API for developers like us. Still, the complexity behind the API shows its ugly face time and again and I believe it is unavoidable as long as the mismatch between Object and Relational world exists. That said, although I have worked with hibernate for many years and have been its advocate in all my organizations, I keep facing newer issues and... <br \/><a class=\"moretag\" href=\"https:\/\/www.gmarwaha.com\/blog\/2009\/08\/26\/hibernate-why-should-i-force-discriminator\/\">Continue reading...<\/a>","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,3,10],"tags":[],"class_list":["post-100","post","type-post","status-publish","format-standard","hentry","category-hibernate","category-java","category-serverside"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/posts\/100","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/comments?post=100"}],"version-history":[{"count":27,"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/posts\/100\/revisions"}],"predecessor-version":[{"id":807,"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/posts\/100\/revisions\/807"}],"wp:attachment":[{"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/media?parent=100"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/categories?post=100"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gmarwaha.com\/blog\/wp-json\/wp\/v2\/tags?post=100"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}