These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: <many-to-one not-found="ignore"> being ignor
PostPosted: Wed Jun 07, 2006 5:57 pm 
Regular
Regular

Joined: Tue Mar 21, 2006 11:01 am
Posts: 65
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:


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 07, 2006 6:15 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
That's a database error, not an Hibernate error. In other words, you're breaking a rule that you've imposed on the database. The not-found="ignore" thing means that when Hibernate issues a select with an ID and no row comes back, no exception will be thrown: you still can't put an arbitrary value into a column that has referential integrity.

To "fix" this, remove the referential integrity (the foreign key relationship) from the database.

A better fix would be to read up on referential integrity, relationships, zero-or-more-to-zero-or-one relationships, and all the rest of the stuff that Hibernate expects you to get right. What you're trying to do will you get on most DBAs' blacklists. In fact, I'm thinking of starting a blacklist just to put you on it... ;)

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 07, 2006 8:49 pm 
Regular
Regular

Joined: Tue Mar 21, 2006 11:01 am
Posts: 65
Well, you're right and wrong.

You're right that I was assuming that the ignore thing would override primary key relationship. The right way, which I soon found, was to use a <properties> element, get rid of the <composite-id> and refer to my mapping through a property-ref. This does, in fact, work.

You're wrong in that I do understand referential integrity. I simply wasn't thinking enough about the fact that my many-to-one was imposing referential integrity, which I DON'T WANT in this situation. I want the relationship to be loose and evanescent. That is the reality of the situation.

You're right in that I should probably read up on "zero-or-more-to-zero-or-one relationships" which is in fact, exactly what this is. Would you care to refer me to such a reading? A quick and dirty google found nothing and I'm quite sure there's nothing for it in the Hibernate manual. No point in getting on the bad side of the DBAs.

By the way, this is the same problem, modified, that you and I discussed much less coherently about two weeks ago.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 07, 2006 9:55 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Cohesion isn't one of my strong points, it's true :) I fly apart at the most inopportune moments.

I didn't mean to imply that there was anything that you weren't understanding; just that checking up on a few of those points might reveal what's going wrong.

I can't think of any particular recommend-worthy reading materials about this. I've picked up most of what I know from various DBAs, Microshaft books about SQLServer, and a couple of O'Reilly books (Java Database Best Practices, or something like that, stands out in my memory, but I don't remember if it had much about this particular issue).

P.S. Thanks for introducing me to a new word. I used to think evanescent was just a band...

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.