Hi,
I'm not experienced Hibernate user thus my question can be silly - if so, get my appologises. I tried to find answer in documentation and forums before posting here but did not succeed.
My real situation is quite complex, but for simplicity it can be reduced to a very trivial case described below.
There are two entities mutually referencing each other (i.e. each has many-to-one relation with another one):
- MutualRefEntity
ADo
- MutualRefEntity
BDo
Foreign keys in DB are declared as deferrable!
Code:
public class [b]MutualRefEntityADo[/b] extends AbstractDo {
private MutualRefEntityBDo b;
private Set<MutualRefEntityBDo> mutualRefEntityBs = new HashSet<MutualRefEntityBDo>();
public MutualRefEntityADo() {
}
public MutualRefEntityBDo getB() {
return b;
}
public void setB(MutualRefEntityBDo value) {
b = value;
}
public Set<MutualRefEntityBDo> getMutualRefEntityBs() {
return mutualRefEntityBs;
}
public void setMutualRefEntityBs(Set<MutualRefEntityBDo> value) {
mutualRefEntityBs = value;
}
}
[b]Mapping for entity A:[/b]
<?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 default-cascade="save-update,merge,refresh">
<class name="MutualRefEntityADo" table="MUTUAL_REF_ENTITY_A" optimistic-lock="version">
<id name="id" type="long" column="ID" unsaved-value="0">
<generator class="sequence">
<param name="sequence">SEQ_MUTUAL_REF_ENTITY_A_id</param>
</generator>
</id>
<version column="VERSION_" name="version_" access="property" unsaved-value="null"/>
<many-to-one class="MutualRefEntityBDo" column="B_ID" name="b"/>
<set inverse="true" lazy="true" name="mutualRefEntityBs">
<key column="A_ID"/>
<one-to-many class="MutualRefEntityBDo"/>
</set>
</class>
</hibernate-mapping>
public class [b]MutualRefEntityBDo [/b]extends AbstractDo {
private MutualRefEntityADo a;
private Set<MutualRefEntityADo> mutualRefEntityAs = new HashSet<MutualRefEntityADo>();
public MutualRefEntityBDo() {
}
public MutualRefEntityADo getA() {
return a;
}
public void setA(MutualRefEntityADo value) {
a = value;
}
public Set<MutualRefEntityADo> getMutualRefEntityAs() {
return mutualRefEntityAs;
}
public void setMutualRefEntityAs(Set<MutualRefEntityADo> value) {
mutualRefEntityAs = value;
}
}
[b]Mapping for entity B:[/b]
<?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 default-cascade="save-update,merge,refresh">
<class name="MutualRefEntityBDo" table="MUTUAL_REF_ENTITY_B" optimistic-lock="version">
<id name="id" type="long" column="ID" unsaved-value="0">
<generator class="sequence">
<param name="sequence">SEQ_MUTUAL_REF_ENTITY_B_id</param>
</generator>
</id>
<version column="VERSION_" name="version_" access="property" unsaved-value="null"/>
<many-to-one class="MutualRefEntityADo" column="A_ID" name="a"/>
<set inverse="true" lazy="true" name="mutualRefEntityAs">
<key column="B_ID"/>
<one-to-many class="MutualRefEntityADo"/>
</set>
</class>
</hibernate-mapping>
Very simple test (session is open and transation is started at setUp()):
Code:
public void testMutualReferencing() throws Exception {
MutualRefEntityADo mreA = new MutualRefEntityADo();
MutualRefEntityBDo mreB = new MutualRefEntityBDo();
mreA.setB(mreB);
mreA.getMutualRefEntityBs().add(mreB);
mreB.setA(mreA);
mreB.getMutualRefEntityAs().add(mreA);
session.save(mreA);
Long mreBId = (Long) session.save(mreB);
[b] commitAndRestartTx(); //just flushes session, commites transaction, clears session and starts new transaction - exception is thrown here![/b]
MutualRefEntityBDo longMreB = (MutualRefEntityBDo) session.load(MutualRefEntityBDo.class, mreBId);
assertNotNull(longMreB);
}
Execution of the test results in the Exception:
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:92)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:222)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2229)
......
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
HibernateTest.commitTx(HibernateTest.java:55)
at HibernateTest.commitAndRestartTx(HibernateTest.java:66)
at HibernateTest.testMutualReferencing(HibernateTest.java:115)
......
Caused by: java.sql.BatchUpdateException: Batch entry 0 insert into MUTUAL_REF_ENTITY_B (VERSION_, A_ID, ID) values (0, [b]NULL, 7) was aborted.[/b]
I cannot understand how to solve this problem. Help please. Thanks in advance!