-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: SecondaryTable, mixed inheritance, and improper SQL inserts
PostPosted: Thu Apr 10, 2008 2:06 pm 
Newbie

Joined: Sun Jan 02, 2005 10:17 pm
Posts: 13
Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version:

Hello everybody,

I have a super class mapped using annotations as follows:

Code:
@Entity
@Table(name="super_duper")
@Inheritance(strategy=Inheritance.SINGLE_TABLE)
@DiscriminatorColumn(name="class_type", discriminatorType=DiscriminatorType.STRING)
public class SuperDuperClass {
   
    protected Long id;
    ......
    ......
}


Then I have a subclass that extends SuperDuperClass and mapped as follows:

Code:
@Entity
@DiscriminatorValue("ChildClass")
@SecondaryTable(name="child_class", pkJoinColumns=@PrimaryKeyJoinColumn(name="super_duper_id"))
public class ChildClass extends SuperDuperClass {
   
   private String name;

   public String getName() {
      return this.name;
   }

   public void setName(String name) {
      this.name = name;
    }

}


The corresponding database tables for the two classes looks like:


SUPER_DUPER
============
* id (PK)
* class_type
* property1
* ......


CHILD_CLASS
==============
* super_duper_id (PK)(FK to the "id" column of table SUPER_DUPER)
* name


Updating ChildClass entities works correctly for ChildClass objects that have *non-null* values for the "name" attribute. The SQL statements generated by Hibernate are follows (and as expected):

Code:
update
   super_duper
set
   .....=?,
   .....=?,
   .....
where
   id=?



update
   child_class
set
   name=?
where
   id=?



However, if I try to update ChildClass entities that have *null* value for the "name" attribute, Hibernate executes that following queries (which are incorrect, I believe):

Code:
update
   super_duper
set
   .....=?,
   .....=?,
   .....
where
   id=?



insert into
   child_class(super_duper_id, name)
values
   (?, ?)




The ChildClass entity already exists, therefore, when Hibernate tries to execute the "INSERT INTO child_class...." statement, a unique constraints violation is thrown by Oracle on the primary key constraint of the CHILD_CLASS table.

First of all, why is Hibernate executing an INSERT into the secondary table (CHILD_CLASS table in this case) when the ChildClass entity already exists?? Hibernate should have generated and execute and UPDATE statement instead for both the SUPER_DUPER and CHILD_CLASS tables.

Also of interest is that this strange behavior happens for records in the secondary table (CHILD_CLASS) which contains all null values for the non primary key columns. If any of the non primary key columns in the secondary table are non null, Hibernate will update the ChildClass record correctly (i.e. generates UPDATE statements for both the SUPER_DUPER and CHILD_CLASS tables).

Is there something wrong with my annotation mappings? Or is this a bug in Hibernate? Any help would be greatly appreciated.

Thanks.


Top
 Profile  
 
 Post subject: Optional secondary tables
PostPosted: Fri Apr 11, 2008 1:39 pm 
Newbie

Joined: Sun Jan 02, 2005 10:17 pm
Posts: 13
After some debugging and tracing through Hibernate code (especially the Hibernate class AbstractEntityPersister and its subclasses), I solved the problem by adding the following annotation for the secondary table:


@Entity
@DiscriminatorValue("ChildClass")
@SecondaryTable(name="child_class", pkJoinColumns=@PrimaryKeyJoinColumn(name="super_duper_id"))
@org.hibernate.annotations.Table(appliesTo="child_class", optional=false)
public class ChildClass extends SuperDuperClass {

private String name;

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

}


The @org.hibernate.annotations.Table attribute "optional" will tell Hibernate to use an outer join. Most importantly, "optional=false" will also tell Hibernate to update the row in the secondary table instead of inserting a new row.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.