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`))