Well, to be more concrete I've wrote the following simple code:
Code:
public class Discriminator {
public Discriminator() {}
public Discriminator(Long id) {this.id = id;}
private Long id;
}
public class ClassA {
private Long id;
public String aName;
}
public class ClassB extends ClassA {
public String bName;
public Discriminator discr;
}
public class ClassC extends ClassB {
public String cName;
}
public class ClassC1 extends ClassC {
public String c1Name;
}
public class ClassC2 extends ClassC {
public String c2Name;
}
public class ClassC3 extends ClassC {
public String c3Name;
}
and the corresponding mapping:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.springsteel.eden.simple" default-access="field">
<class name="Discriminator"
table="DISCRIMINATOR">
<id name="id"
column="DISCRIMINATOR_ID"
type="long">
</id>
</class>
<class name="ClassA"
table="CLASS_A">
<id name="id" column="ID" type="long">
<generator class="native"/>
</id>
<discriminator column="DISCRIMINATOR_ID" insert="false" formula="1"/> <!-- les us assume that correct formula will be used -->
<property name="aName" column="A_NAME"/>
</class>
<joined-subclass name="ClassB"
table="CLASS_B" extends="ClassA">
<key column="ID"/>
<property name="bName" column="B_NAME"/>
<many-to-one column="DISCRIMINATOR_ID"
name="discr"
cascade="all"
class="Discriminator"/>
</joined-subclass>
<joined-subclass name="ClassC" extends="ClassB"
table="CLASS_C">
<key column="ID"/>
<property name="cName" column="C_NAME"/>
</joined-subclass>
<subclass name="ClassC1" extends="ClassC" discriminator-value="100">
<property name="c1Name" column="C1_NAME"/>
</subclass>
<subclass name="ClassC2" extends="ClassC" discriminator-value="200">
<property name="c2Name" column="C2_NAME"/>
</subclass>
<subclass name="ClassC3" extends="ClassC" discriminator-value="300">
<property name="c3Name" column="C3_NAME"/>
</subclass>
</hibernate-mapping>
After this execution of the following code fails (les us assume that session is a valid hibernate session):
Code:
List<Discriminator> types = new ArrayList<Discriminator>();
types.add(new Discriminator(100L));
types.add(new Discriminator(200L));
types.add(new Discriminator(300L));
session.save(types.get(0));
session.save(types.get(1));
session.save(types.get(2));
ClassC1 c1 = new ClassC1();
c1.discr = types.get(0);
c1.aName = "AAA";
c1.bName = "BBB";
c1.cName = "CCC";
c1.c1Name = "C1C1C1";
session.save(c1);
with the following trace (MySQL 5.0.27 is used):
Code:
Hibernate: insert into DISCRIMINATOR (DISCRIMINATOR_ID) values (?)
Hibernate: insert into DISCRIMINATOR (DISCRIMINATOR_ID) values (?)
Hibernate: insert into DISCRIMINATOR (DISCRIMINATOR_ID) values (?)
Hibernate: insert into CLASS_A (A_NAME) values (?)
Hibernate: insert into CLASS_B (B_NAME, DISCRIMINATOR_ID, ID) values (?, ?, ?)
Hibernate: insert into CLASS_C (C_NAME, C1_NAME, ID) values (?, ?, ?)
Hibernate: insert into CLASS_C (ID) values (?)
2009-04-16 12:09:29,952 WARN org.hibernate.util.JDBCExceptionReporter :: SQL Error: 1062, SQLState: 23000
2009-04-16 12:09:29,952 ERROR org.hibernate.util.JDBCExceptionReporter :: Duplicate entry '1' for key 1
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not insert: [com.springsteel.eden.simple.ClassC1]
At the same time exported schema looks well: there are two tables for A and B, B contains the discriminator id and Cx subhierarchy is persisted into single table CLASS_C.
Could you please explain why Hibernate writes ClassC with same id twice?
Thank you in advance.