-->
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.  [ 3 posts ] 
Author Message
 Post subject: No nullability check for collection elements in 2.1.7c?
PostPosted: Thu Jan 20, 2005 10:14 am 
Newbie

Joined: Thu Jan 20, 2005 8:21 am
Posts: 2
Hi!

When a property of an element in a list is set to not-null and you try to insert a null, then you will get a SQL exception from the JDBC driver. The nullability is not checked before trying to persist the value. This will also cause the parent to be not stored in the DB while Hibernate believes it is, if you rollback your transaction based on the exception.

When issuing a flush() or saveOrUpdate() after correcting the invalid value, Hibernate issues an update instead of an insert for the parent, causing another SQL exception.

Mapping:
Code:
   <class name="test.data.A" table="tblA">
      <id name="id" column="id" type="int">
         <generator class="native"/>
      </id>
      <property name="value" column="value" type="string"/>
      <list name="listOfB" table="BofA">
         <key column="id"/>
         <index column="idx"/>
         <composite-element class="test.data.B">            
            <property name="value" type="string" not-null="true"/>
         </composite-element>
      </list>
   </class>


Java Code:
Code:
      System.out.println("*** Creating A with invalid B as child ***");
      A a = new A(new LinkedList());      
      a.setValue("Test");
      B b = new B(null); // this B violates not-null
      a.getListOfB().add(b); // this B violates not-null
      
      Session s = sessionFactory.openSession();
      Transaction t = s.beginTransaction();
      try {
          System.out.println("*** calling saveOrUpdate ***");
          s.saveOrUpdate(a);
          t.commit();
      } catch (Exception e) {
          e.printStackTrace();
          t.rollback();
      }
      
       System.out.println("*** Changing A / Updating B to valid ***");
      a.setValue("changed");
      b.setValue("valid now"); // invalid, causes not-null violation

      try {
          System.out.println("*** Flushing ***");
          s.flush();
          t.commit();
      } catch (Exception e) {
          e.printStackTrace();
          t.rollback();
      }


Output:
Code:
*** Creating A with invalid B as child ***
*** calling saveOrUpdate ***
Hibernate: insert into tblA (value, id) values (?, null)
Hibernate: call identity()
Hibernate: insert into BofA (id, idx, value) values (?, ?, ?)
2005-01-20 14:45:15,687 [main] WARN  net.sf.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: null
2005-01-20 14:45:15,687 [main] ERROR net.sf.hibernate.util.JDBCExceptionReporter - failed batch
2005-01-20 14:45:15,687 [main] WARN  net.sf.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: null
2005-01-20 14:45:15,687 [main] ERROR net.sf.hibernate.util.JDBCExceptionReporter - failed batch
2005-01-20 14:45:15,687 [main] ERROR net.sf.hibernate.impl.SessionImpl - Could not synchronize database state with session
net.sf.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
   at net.sf.hibernate.exception.ErrorCodeConverter.handledNonSpecificException(ErrorCodeConverter.java:90)
   at net.sf.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:79)
   at net.sf.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:30)
   at net.sf.hibernate.impl.BatcherImpl.convert(BatcherImpl.java:325)
   at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:134)
   at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2441)
   at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2395)
   at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2260)
   at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
   at test.Tester.main(Tester.java:65)
Caused by: java.sql.BatchUpdateException: failed batch
   at org.hsqldb.jdbc.jdbcStatement.executeBatch(Unknown Source)
   at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(Unknown Source)
   at net.sf.hibernate.impl.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:54)
   at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:127)
   ... 5 more
*** Changing A / Updating B to valid ***
*** Flushing ***
Hibernate: update tblA set value=? where id=?
2005-01-20 14:45:15,703 [main] ERROR net.sf.hibernate.impl.SessionImpl - Could not synchronize database state with session
net.sf.hibernate.HibernateException: Batch update row count wrong: 0
   at net.sf.hibernate.impl.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:65)
   at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:127)
   at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2441)
   at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2392)
   at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2260)
   at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
   at test.Tester.main(Tester.java:78)
2005-01-20 14:45:15,718 [Secondary finalizer] WARN  net.sf.hibernate.impl.SessionImpl - unclosed connection, forgot to call close() on your session?
2005-01-20 14:45:15,906 [Secondary finalizer] INFO  net.sf.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool: jdbc:hsqldb:file:testdb


Hibernate version: 2.1.7c

Name and version of the database you are using:
hsqldb_1_7_2_4, reproducible also with MS SQL Server 2000

Is this a bug, or am I mistreating Hibernate by using flush() in the above example. The same output is produced for saveOrUpdate() as second call, too, however. Or is it not allowed to roll back the transaction after the first exception?

Thanks in advance,
Martin


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 20, 2005 10:18 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
How can you have a second Exception (I quickly skipped the rest of your posting as it seems not relevant) if the Hibernate documentation clearly says that you have to discard your Session right after the first Exception?

It doesn't matter what exception is thrown by violating a not-null constraint, the outcome is the same.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 20, 2005 10:28 am 
Newbie

Joined: Thu Jan 20, 2005 8:21 am
Posts: 2
You are right. Shame on me, I overlooked the obvious.

Thanks for your fast reply.

Best Regards,
Martin


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 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.