Hi All
I've a parent->child relation ClassA->ClassB. The foreign key on the B side is composed of a foreign key column (A_PID) and a second column which is also part of the primary key of B (SYSTEM_ID).
This means, that I have to set the many-to-one to update="false" and insert="false". In order to get the foreign key column on the B side correctly set I've written an Interceptor which sets the A_PID column onFlushDirty and onSave.
Please ee the code below for the details.
As far as I understand in Hibernate 3 I could cope with this by replacenig the
Code:
<many-to-one name="classA" cascade="all" class="hello.ClassA" update="false" insert="false">
<column name="A_PID"/>
<column name="SYSTEM_ID"/>
</many-to-one>
with
Code:
<many-to-one name="classA" cascade="all" class="hello.ClassA">
<column name="A_PID"/>
<formula name="SYSTEM_ID"/>
</many-to-one>
No Interceptor would be necessary.
Unfortunately I can't wait for Hibernate 3, which means I'm asking if somebodey knows about a nicer solution. I'm especially not happy of writing a piece of code in the Interceptor for every relation, because I've dozens of them.
TIA
Ernst
Hibernate version:2.1.6
Mapping documents:Code:
<hibernate-mapping>
<class name="hello.ClassA" table="TABLE_A">
<composite-id name="pk" class="hello.CapiPK">
<key-property name="pid" column="PID"/>
<key-property name="systemId" column="SYSTEM_ID"/>
</composite-id>
<set name="B" table="TABLE_B" cascade="all" inverse="true">
<key>
<column name="A_PID"/>
<column name="SYSTEM_ID"/>
</key>
<one-to-many class="hello.ClassB"/>
</set>
</class>
</hibernate-mapping>
Code:
<hibernate-mapping>
<class name="hello.ClassB" table="TABLE_B">
<composite-id name="pk" class="hello.CapiPK">
<key-property name="pid" column="PID"/>
<key-property name="systemId" column="SYSTEM_ID"/>
</composite-id>
<many-to-one name="classA" cascade="all" class="hello.ClassA" update="false" insert="false">
<column name="A_PID"/>
<column name="SYSTEM_ID"/>
</many-to-one>
<property name="apid" column="A_PID"/>
<property name="payload"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
public class CapiInterceptor implements Interceptor {
...
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState,
Object[] previousState, String[] propertyNames, Type[] arg5) throws CallbackException {
System.out.println("Set the dirty flags up on update");
if (entity instanceof ClassB) {
ClassB b = (ClassB)entity;
int apidPos = getAPidPos(propertyNames);
if (b.getClassA()!=null) {
currentState[apidPos]=b.getClassA().getPk().getPid();
}
return true;
}
return false;
}
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) throws CallbackException {
if (entity instanceof ClassB) {
ClassB b = (ClassB)entity;
int apidPos = getAPidPos(propertyNames);
if (state[apidPos]==null && b.getClassA()!=null) {
state[apidPos]=b.getClassA().getPk().getPid();
}
return true;
}
return false;
}
private int findStringIgnoreCase(String[] array, String inSearchString) {
for (int i = 0; i < array.length; i++) {
if (inSearchString.equalsIgnoreCase(array[i])) {
return i;
}
}
return -1;
}
private int getAPidPos(String[] array) throws CallbackException {
int pos = findStringIgnoreCase(array, "APid");
if (pos==-1) {
throw new CallbackException("Property APid not found.");
}
return pos;
}
}
Full stack trace of any exception that occurs:
no exceptions
Name and version of the database you are using:
Oracle 9.2
Debug level Hibernate log excerpt:
na