I'm a little curious how hibernate manages foreign keys. I'm seeing something
very strange in my application. I have a base table for each table in my schema,
along with a history table, and a view. I read/write to the view, and that view
has triggers on it which write to the history table.
What i'm noticing in the history table is that if I have a foreign key relationship,
the child part of that is getting inserted, and then updated.
Here's the parent, which has no clue about the child (deliberately):
<class name="com.fiberlink.thirdpartybilling.contract.Contract"
table="TPB_CONTRACT_V">
<id name="id" column="ID">
<generator class="sequence">
<param name="sequence">TPB_CONTRACT_SEQUENCE</param>
</generator>
</id>
<version name="version" column="VERSION_ID" type="long"/>
<property name="name" column="NAME" length="50"/>
<component name="startDate">
<property name="month" column="MONTH_START" />
<property name="year" column="YEAR_START" />
</component>
<property name="contractLength" column="CONTRACT_LENGTH" />
<many-to-one name="customer" column="CUSTOMER_ID"
class="com.fiberlink.thirdpartybilling.customer.Customer" />
<component name="modelAudit">
<property name="auditUser" column="AUDIT_USER" />
<property name="auditEventId" column="AUDIT_EVENT_ID" />
<property name="auditDate" column="AUDIT_DATE" />
<property name="auditAction" column="AUDIT_ACTION" />
</component>
</class>
and the child:
<class name="com.fiberlink.thirdpartybilling.contract.Pricing"
table="TPB_PRICING_V"
abstract="true">
<id name="id" column="ID">
<generator class="sequence">
<param name="sequence">TPB_PRICING_SEQUENCE</param>
</generator>
</id>
<discriminator column="TYPE" type="string" length="1"/>
<version name="version" column="VERSION_ID" type="long" />
<component name="effectiveDate">
<property name="month" column="MONTH_EFFECTIVE" />
<property name="year" column="YEAR_EFFECTIVE" />
</component>
<component name="modelAudit">
<property name="auditUser" column="AUDIT_USER" />
<property name="auditEventId" column="AUDIT_EVENT_ID" />
<property name="auditDate" column="AUDIT_DATE" />
<property name="auditAction" column="AUDIT_ACTION" />
</component>
<many-to-one name="contract" column="CONTRACT_ID"
class="com.fiberlink.thirdpartybilling.contract.Contract" />
[ snipping out the subclasses ]
</class>
I'm keeping the session open for the duration of the web request
using spring's TransactionSynchronizationManager. So, when i
flush the session upon the end of the request, it should be inserting
all my records, the parent first, and then each of the children.
However, i can tell in the logs that it's inserting the Contract item
first, and then the Pricing items. But for some reason it's binding
null to the CONTRACT_ID column on insert, and updating it later.
This is causing unwanted items in my history tables.
Any clue why it does this, or how I can get around it?
Hibernate version:
3.0.5
Mapping documents:
Code between sessionFactory.openSession() and session.close():
Full stack trace of any exception that occurs:
Name and version of the database you are using:
The generated SQL (show_sql=true):
948903 [http-8080-Processor22] DEBUG org.hibernate.SQL - insert into TPB_CONTRACT_V (VERSION_ID, NAME, MONTH_START, YEAR_START, CONTRACT_LENGTH, CUSTOMER_ID, AUDIT_USER, AUDIT_EVENT_ID, AUDIT_DATE, AUDIT_ACTION, ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
948908 [http-8080-Processor22] DEBUG org.hibernate.SQL - insert into TPB_PRICING_V (VERSION_ID, MONTH_EFFECTIVE, YEAR_EFFECTIVE, AUDIT_USER, AUDIT_EVENT_ID, AUDIT_DATE, AUDIT_ACTION, CONTRACT_ID, TYPE, ID) values (?, ?, ?, ?, ?, ?, ?, ?, 'S', ?)
948910 [http-8080-Processor22] DEBUG org.hibernate.type.StringType - binding null to parameter: 7
Debug level Hibernate log excerpt:
|