-->
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.  [ 7 posts ] 
Author Message
 Post subject: Problem with "join inheritance hierarchy" deeper t
PostPosted: Sun Feb 26, 2006 7:20 am 
Newbie

Joined: Wed Jan 07, 2004 12:02 pm
Posts: 15
Location: Herne, Germany
I made up a most simple scenario to show what I want to do and the problem that occurs:

I have the following inheritance hierarchy: Base <- Sub <- SubSub

If I set up a clean database and store a Base everything works.
If I set up a clean database and store a Sub everything works.
If I set up a clean database and store a SubSub I receive an exception (see below).

Thanks for any help.

Hibernate version:
Hibernate 3.1.2

annotated classes:
Code:
package test.ejb3.sc002;

import java.io.Serializable;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;

@Entity
@Table(name = "Base")

@Inheritance(strategy = InheritanceType.JOINED)
public class Base
   implements Serializable
{
   @Id @GeneratedValue(strategy = GenerationType.AUTO)
   private long id;

   public Base()
   {}

   @Id @GeneratedValue(strategy = GenerationType.AUTO)
   public long getId()
   {
      return this.id;
   }

   protected void setId(long id)
   {
      this.id = id;
   }
}

Code:
package test.ejb3.sc002;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrimaryKeyJoinColumn;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Table;


@Entity
@Table(name = "Sub")
@PrimaryKeyJoinColumn(name = "idSuperBase")
public class Sub extends Base implements Serializable
{
   public Sub() {}
}

Code:
package test.ejb3.sc002;

import javax.persistence.PrimaryKeyJoinColumn;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Table;


@Entity
@Table(name = "SubSub")
@PrimaryKeyJoinColumn(name = "idSuperSub")
public class SubSub extends Sub implements Serializable
{
   public SubSub() {}
}



Mapping documents:
Code:
<persistence>
   <persistence-unit
     name="gsdEntityManager"
     transaction-type="JTA">
     <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>test.ejb3.sc002.Base</class>
        <class>test.ejb3.sc002.Sub</class>
        <class>test.ejb3.sc002.SubSub</class>
        <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>
         <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
         <property name="hibernate.connection.username" value="root"/>
         <property name="hibernate.connection.password" value=""/>
         <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/ruu_gsd_test"/>
         <property name="hibernate.max_fetch_depth" value="3"/>
       
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.use_sql_comments">true</property>
     </properties>
   </persistence-unit>
</persistence>


Code between sessionFactory.openSession() and session.close():
Code:
package test.ejb3.sc002;

import java.util.HashMap;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class Test
{
   private void storeBase()
   {
      EntityManager entityManager =
         Persistence.createEntityManagerFactory(
               "gsdEntityManager", new HashMap()).createEntityManager();
      EntityTransaction entityTransaction = entityManager.getTransaction();
      
      entityTransaction.begin();
      
      Base base = new Base();
      entityManager.persist(base);
      
      entityManager.flush();
      entityTransaction.commit();
      entityManager.close();
      
      System.out.println("stored base");
   }
   
   private void storeSub()
   {
      EntityManager entityManager =
         Persistence.createEntityManagerFactory(
               "gsdEntityManager", new HashMap()).createEntityManager();
      EntityTransaction entityTransaction = entityManager.getTransaction();
      
      entityTransaction.begin();
      
      Sub sub = new Sub();
      entityManager.persist(sub);
      
      entityManager.flush();
      entityTransaction.commit();
      entityManager.close();
      
      System.out.println("stored sub");      
   }
   
   private void storeSubSub()
   {
      EntityManager entityManager =
         Persistence.createEntityManagerFactory(
               "gsdEntityManager", new HashMap()).createEntityManager();
      EntityTransaction entityTransaction = entityManager.getTransaction();
      
      entityTransaction.begin();
      
      SubSub subSub = new SubSub();
      entityManager.persist(subSub);
      
      entityManager.flush();
      entityTransaction.commit();
      entityManager.close();
      
      System.out.println("stored subsub");      
   }
   
   public static void main(String[] args)
   {
      Test test = new Test();

      test.storeBase();
      test.storeSub();
      test.storeSubSub();
   }
}



Full stack trace of any exception that occurs:
Code:
12:01:10,483 WARN  org.hibernate.util.JDBCExceptionReporter:71> SQL Error: 1452, SQLState: 23000
12:01:10,483 ERROR org.hibernate.util.JDBCExceptionReporter:72> Cannot add or update a child row: a foreign key constraint fails (`ruu_gsd_test/subsub`, CONSTRAINT `fks_SubSub2Sub` FOREIGN KEY (`idSuperSub`) REFERENCES `sub` (`id`))
org.hibernate.exception.ConstraintViolationException: could not insert: [test.ejb3.sc002.SubSub]
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:69)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2078)
   at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2407)
   at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:37)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:243)
   at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:269)
   at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:167)
   at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:101)
   at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:131)
   at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87)
   at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)
   at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:642)
   at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:616)
   at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:620)
   at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:127)
   at test.ejb3.sc002.Test.storeSubSub(Test.java:59)
   at test.ejb3.sc002.Test.main(Test.java:74)
Caused by: java.sql.SQLException: Cannot add or update a child row: a foreign key constraint fails (`ruu_gsd_test/subsub`, CONSTRAINT `fks_SubSub2Sub` FOREIGN KEY (`idSuperSub`) REFERENCES `sub` (`id`))
   at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2928)
   at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1571)
   at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1124)
   at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:676)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1166)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1082)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1067)
   at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2065)
   ... 15 more



Name and version of the database you are using:
RDBMS: MySQL, version: 5.0.16

sql ddl:
Code:
DROP DATABASE IF EXISTS test;

CREATE DATABASE IF NOT EXISTS test;

DROP TABLE IF EXISTS test.Base;
DROP TABLE IF EXISTS test.Sub;
DROP TABLE IF EXISTS test.SubSub;

CREATE TABLE test.Base
(
   id bigint(20) default NULL NOT NULL auto_increment,

   PRIMARY KEY
   (
      id
   )
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE test.Sub
(
   id bigint(20) NOT NULL auto_increment,

   idSuperBase bigint(20) default NULL,

   PRIMARY KEY
   (
      id
   ),

   KEY keySuperBase
   (
      idSuperBase
   )
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE test.SubSub
(
   id bigint(20) NOT NULL auto_increment,

   idSuperSub bigint(20) default NULL,

   PRIMARY KEY
   (
      id
   ),

   KEY keySuperSub
   (
      idSuperSub
   )
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE test.Sub
   ADD CONSTRAINT fks_Sub2Base FOREIGN KEY
(
   idSuperBase
) REFERENCES Base
  (
     id
  );

ALTER TABLE test.SubSub
   ADD CONSTRAINT fks_SubSub2Sub FOREIGN KEY
(
   idSuperSub
) REFERENCES Sub
  (
     id
  );


The generated SQL (show_sql=true):
Code:
Hibernate:
    /* insert test.ejb3.sc002.Base
        */ insert
        into
            Base
           
        values
            ( )
...
Hibernate:
    /* insert test.ejb3.sc002.Sub
        */ insert
        into
            Base
           
        values
            ( )
Hibernate:
    /* insert test.ejb3.sc002.Sub
        */ insert
        into
            Sub
            (idSuperBase)
        values
            (?)
...
Hibernate:
    /* insert test.ejb3.sc002.SubSub
        */ insert
        into
            Base
           
        values
            ( )
Hibernate:
    /* insert test.ejb3.sc002.SubSub
        */ insert
        into
            Sub
            (idSuperBase)
        values
            (?)
Hibernate:
    /* insert test.ejb3.sc002.SubSub
        */ insert
        into
            SubSub
            (idSuperSub)
        values
            (?)

Debug level Hibernate log excerpt:
Code:
12:01:10,423 DEBUG net.sf.ehcache.CacheManager:196> Attempting to create an existing instance. Existing instance returned.
...
12:01:10,483 WARN  org.hibernate.util.JDBCExceptionReporter:71> SQL Error: 1452, SQLState: 23000
12:01:10,483 ERROR org.hibernate.util.JDBCExceptionReporter:72> Cannot add or update a child row: a foreign key constraint fails (`ruu_gsd_test/subsub`, CONSTRAINT `fks_SubSub2Sub` FOREIGN KEY (`idSuperSub`) REFERENCES `sub` (`id`))


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 02, 2006 12:19 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Hibernate does not generate this schema. idSuperBase should be the pk of Sub, etc

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 02, 2006 2:59 am 
Newbie

Joined: Wed Jan 07, 2004 12:02 pm
Posts: 15
Location: Herne, Germany
emmanuel wrote:
Hibernate does not generate this schema. idSuperBase should be the pk of Sub, etc

idSuperBase is the foreign key of Sub to it's Base superclass. If it was the primary key of Sub at the same time that would mean I could create at most one Sub object for each Base object, wouldn't it? But a Base object should be able to have many Sub objects in a inheritance relation.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 02, 2006 7:54 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
ruuit wrote:
emmanuel wrote:
Hibernate does not generate this schema. idSuperBase should be the pk of Sub, etc

idSuperBase is the foreign key of Sub to it's Base superclass. If it was the primary key of Sub at the same time that would mean I could create at most one Sub object for each Base object, wouldn't it?


Of course that's what inheritance means. A Cat is an Animal I cannot have 2 different cats for the same animal instance at least in the world I live in.

What you want is associations

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 06, 2006 3:37 pm 
Beginner
Beginner

Joined: Tue Jun 28, 2005 2:43 pm
Posts: 29
Location: Silicon Valley
yes, ruuit, it sounds like you are mixing the concepts of inheritance and parent-child association. In inheritance, a superclass may have multiple subclasses, but each instance of the subclass represents exactly one instance of the superclass. Therefore each row (instance) in the superclass table is associated with at most one row (extending the same instance) in the subclass table.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 29, 2006 1:29 pm 
Beginner
Beginner

Joined: Sat Oct 08, 2005 2:13 am
Posts: 47
Hello

I am very interested to know your idea about my problem.

I design my database to support multilanguage, something like this:

Code:
table Patient_Info (id, admit_date, status, type, discharge_date)
table Patient_info_locale (patient_id, locale_id, name, family)


[name and family in second table will be inserted in different languages]

at first, I create a class for each and made a master/detail relation between them. but it made many problems for other programmers. using this strategy is very hard. because you always should challenge with the collections and there are many tables in the databse like this one. i want my programmers work with only one class not a class with a collection. I mean if I need some info from a patient I use PatientInfoLocale class and access to all attribute of patient with advantages of inheritance. I am detested using PatientInfo class and then load its collection (eg. patientInfo.getPatientInfoLocales() )

in my opinion, both patient_info and patient_info_locale are identical conceptually. so I decided to use joined inheritance strategy.

now, It buffled me. because in this strategy the subtype has the same primary key in the super type. so , for example, if the information of a patient being inserted in two different language (for example English and Russian) the primary key constraint will violated and insertion will failed.
what will happen on locale_id?

how can I manage it? please help me out.

thank you so much in advance.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 21, 2007 2:00 pm 
Beginner
Beginner

Joined: Thu Oct 16, 2003 7:25 pm
Posts: 38
Location: New York City
In order to allow multiple languages, it must be a collection of some sort in the master pojo. There's no other way.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.