In brief, the issue is that in spite of the fact that an attribute of not-found="ignore" is present in the many-to-one mapping from CallLogEntry to ContactName, database errors are being generated.
ContactName has a composite-id primary key on session and telephone number. There is no requirement that the same combination in CallLogEntry have a match in ContactName. And yet database is throwing a constraint violation when trying to insert a row where this combination of fields in CallLogEntry does not map to an entry in ContactName.
So it seems as though the not-found="ignore" is being ignored.
I'm guessing that the problem may be that many-to-one insists on a foreign key - primary key mapping. But this isn't really a foreign-key relationship. It's a temporary association which may or may not be present. I would like to be able to use <many-to-one> for such a case but it may not be possible.
Can someone suggest an alternate mapping strategy for this case?
Please note I am using Hibernate version 3.0.5. Changing is not an option.
Hibernate version: 3.0.5
Mapping documents:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="ContactName"
table="contact_name">
<composite-id name="id"
class="ContactName$Id">
<key-many-to-one name="lsession" column="lsession_id" />
<key-property name="tn" column="phone_number" length="100"/>
</composite-id>
<property name="firstName" column="first_name" length="50"/>
<property name="lastName" column="last_name" length="50"/>
<property name="nickname" length="50"/>
<property name="lsessionId" column="lsession_id" insert="false" update="false"/>
</class>
<query name="deleteContactsBySession"><![CDATA[
delete ContactName where lcmSessionId =:lsessid
]]></query>
</hibernate-mapping>
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="CallLogEntry"
table="call_log_entry">
<id name="id" type="java.lang.Long" column="id">
<generator class="seqhilo">
<param name="max_lo">100</param>
<param name="sequence">call_log_entry_seq</param>
</generator>
</id>
<many-to-one name="lsession" not-null="true">
<column name="lsession_id" index="call_log_ndx"/>
</many-to-one>
...
<component name="otherTn"
class="TelephoneNumber">
<property name="rawTn" column="other_tn" length="20"
not-null="true" />
</component>
<many-to-one name="contactName" not-null="false" not-found="ignore"
class="ContactName" insert="false" update="false" >
<column name="lsession_id" />
<column name="other_tn"/>
</many-to-one>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():note: HibernateUtility works similarly to the one in CaveatEmptor
Code:
Session sess = HibernateUtility.getSession();
HibernateUtility.beginTransaction();
int batchsize = HibernateUtility.getJdbcBatchSize();
int i = 1;
for (Iterator it = callLogs.iterator(); it.hasNext(); i++) {
CallLogEntry calllog = (CallLogEntry) it.next();
sess.save(calllog);
if (i % batchsize == 0) {
sess.flush();
sess.clear();
}
}
HibernateUtility.commitTransaction();
Full stack trace of any exception that occurs:Code:
com.whatever.DbException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at com.whatever.HibernateUtility.commitTransaction(HibernateUtility.java:256)
at com.whatever.CallLogDao.saveCallLogs(CallLogDao.java:48)
at com.whatever.CallLogDaoTestCase.setUp(CallLogDaoTestCase.java:39)
at junit.framework.TestCase.runBare(TestCase.java:125)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:436)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:311)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:74)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:181)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:226)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:136)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
at com.whatever.HibernateUtility.commitTransaction(HibernateUtility.java:251)
... 10 more
Caused by: java.sql.BatchUpdateException: ORA-02291: integrity constraint (SANDBOX.FKF71B2316F4EA2888) violated - parent key not found
at oracle.jdbc.dbaccess.DBError.throwBatchUpdateException(DBError.java:459)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:4133)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:57)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:174)
... 18 more
Name and version of the database you are using:Oracle 9.2
The generated SQL (show_sql=true):Code:
insert into call_log_entry (lsession_id, ... other_tn, id) values (?, ... ?, ?)
Debug level Hibernate log excerpt: