I am attempting to save a transient object and when the operation fails the transient object's id is set (this is bad) but the record is not inserted into the database, as expected.
I have scoured the forums and FAQ's and I can't find a definitive answer to this issue. I'm using Hibernate version 2.0.1 17 June 2003.
This is what I'm doing (and I'll follow it up with a code snippet):
1) Create a new instance of my object to save and set attributes. At this point the object.getId() == null, as it should.
2) Get Hibernate Session, get/start Hibernate Transaction.
3) session.save() the object (this does NOT throw an exception).
4) Tx.commit() (this DOES throw an exception)
5) Cleanup session/transaction objects.
At this point the database shows that the object's attributes were not persisted as I expected. However the Object's identifier is now not null, it contains a valid value, like 22. When I modify the object's attributes and attempt to save it again, it fails and Hibernate something like "No row found where id: 22".
I'm trying to understand the semantics of session.save(), session.flush() and tx.commit(). There are numerous postings on this, and from this I understand that session.save() sets up the SQL query (AND get's the ID for the object if it's null!), session.flush() sends the command to the database, and tx.commit()'s the statement.
Here is the code, I'll try to provide only useful snippets and not 6 pages of debug statements.
Any help would be greatly appreciated!!!
Block of code:
Code:
System.err.println("id is: " + hibernateObject.getId());
Session session = null;
Transaction tx = null;
boolean didCommit = false;
try {
session = SessionFactory.openSession();
tx = session.beginTransaction();
session.save(hibernateObject);
System.err.println("logic succeeded.");
tx.commit(); // this flushes the session.
System.err.println("committed transaction.");
didCommit = true;
}
catch (HibernateException he) {
System.err.println("save exception: " + he.getMessage() );
if (tx != null) {
System.err.println("rolling back transaction...");
tx.rollback();
}
throw he;
}
finally {
System.err.println("did commit? " + didCommit);
if (session != null) {
session.close();
}
}
System.err.println("id is: " + hibernateObject.getId());
What gets printed out from above:
Code:
id is: null
logic succeeded.
save exception: Could not synchronize database state with session: ORA-02291: integrity constraint (blah blah blah)
rolling back transaction...
did commit? false
id is: 22
I designed the test to fail by the way. Actually this was a unittest I wrote. When I try to save the object again, I get the "No row found for id 22" error message.
My hbm.xml file...
Code:
<class
name="com.qrs.itm.dao.admin.organization.Organization"
table="QI_ORGANIZATION"
dynamic-update="false"
dynamic-insert="false"
>
<id
name="id"
column="ORGANIZATION_ID"
type="com.qrs.itm.dao.admin.organization.OrganizationIDType"
unsaved-value="null"
>
<generator class="com.qrs.itm.dao.admin.organization.OrganizationHiLoGenerator">
<param name="table">QI_SEQUENCES</param>
<param name="column">ORGANIZATION</param>
<param name="max_lo">20</param>
</generator>
</id>
<property
name="name"
type="java.lang.String"
update="true"
insert="true"
column="ORGANIZATION_NAME"
length="64"
/>
I'm using custom types and my custom HiLoGenerator just simply uses Hibernate's TableHiLoGenerator.
I'll provide relevant snippets of the hibernate.log debug file:
Code:
INFO net.sf.hibernate.cfg.Environment - Hibernate 2.0.1
INFO net.sf.hibernate.cfg.Environment - loaded properties from resource hibernate.properties: {hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver, hibernate.cglib.use_reflection_optimizer=true, hibernate.dialect=net.sf.hibernate.dialect.Oracle9Dialect, hibernate.jdbc.use_streams_for_binary=true, hibernate.jdbc.batch_size=0, hibernate.connection.username=SGarcia_itm1, hibernate.connection.url=jdbc:oracle:thin:@RCAITMD01:1521:ITMD01, hibernate.show_sql=false, hibernate.connection.password=SGarcia_itm1, hibernate.connection.pool_size=10, hibernate.statement_cache.size=0}
INFO net.sf.hibernate.cfg.Environment - using java.io streams to persist binary types
INFO net.sf.hibernate.cfg.Environment - using CGLIB reflection optimizer
INFO net.sf.hibernate.cfg.Environment - JVM proxy support: true
INFO net.sf.hibernate.cfg.Configuration - Mapping resource: com/qrs/itm/dao/admin/organization/Organization.hbm.xml
DEBUG net.sf.hibernate.util.DTDEntityResolver - trying to locate http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd in classpath under net/sf/hibernate/
DEBUG net.sf.hibernate.util.DTDEntityResolver - found http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd in classpath
INFO net.sf.hibernate.cfg.Binder - Mapping class: com.qrs.itm.dao.admin.organization.Organization -> QI_ORGANIZATION
DEBUG net.sf.hibernate.cfg.Binder - Mapped property: id -> ORGANIZATION_ID, type: com.qrs.itm.dao.admin.organization.OrganizationIDType
DEBUG net.sf.hibernate.cfg.Binder - Mapped property: name -> ORGANIZATION_NAME, type: string
DEBUG net.sf.hibernate.cfg.Binder - Mapped property: shortName -> SHORT_NAME, type: string
[snip]
INFO net.sf.hibernate.impl.SessionFactoryImpl - building session factory
DEBUG net.sf.hibernate.impl.SessionFactoryImpl - instantiating session factory with properties: {hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver, hibernate.dialect=net.sf.hibernate.dialect.Oracle9Dialect, hibernate.jdbc.use_streams_for_binary=true, hibernate.jdbc.batch_size=0, hibernate.connection.username=SGarcia_itm1, hibernate.connection.url=jdbc:oracle:thin:@RCAITMD01:1521:ITMD01, hibernate.show_sql=false, hibernate.connection.password=SGarcia_itm1, hibernate.statement_cache.size=0, hibernate.connection.pool_size=10}
INFO net.sf.hibernate.dialect.Dialect - Using dialect: net.sf.hibernate.dialect.Oracle9Dialect
INFO net.sf.hibernate.connection.DriverManagerConnectionProvider - Hibernate connection pool size: 10
INFO net.sf.hibernate.connection.DriverManagerConnectionProvider - using driver: oracle.jdbc.driver.OracleDriver at URL: jdbc:oracle:thin:@RCAITMD01:1521:ITMD01
INFO net.sf.hibernate.connection.DriverManagerConnectionProvider - connection properties: {user=SGarcia_itm1, password=SGarcia_itm1}
INFO net.sf.hibernate.impl.SessionFactoryImpl - Use outer join fetching: true
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - total checked-out connections: 0
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - opening new JDBC connection
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - created connection to: jdbc:oracle:thin:@RCAITMD01:1521:ITMD01, Isolation Level: 2
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - returning connection to pool, pool size: 1
INFO net.sf.hibernate.impl.SessionFactoryImpl - Use scrollable result sets: true
DEBUG net.sf.hibernate.impl.SessionFactoryObjectFactory - initializing class SessionFactoryObjectFactory
DEBUG net.sf.hibernate.impl.SessionFactoryObjectFactory - registered: 2c90829anullfa62db51null00fanull62db5972null0000 (unnamed)
INFO net.sf.hibernate.impl.SessionFactoryObjectFactory - no JDNI name configured
INFO net.sf.hibernate.impl.SessionFactoryImpl - Query language substitutions: {}
DEBUG net.sf.hibernate.impl.SessionFactoryImpl - instantiated session factory
DEBUG net.sf.hibernate.impl.SessionImpl - opened session
DEBUG net.sf.hibernate.transaction.JDBCTransaction - begin
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - total checked-out connections: 0
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - using pooled JDBC connection, pool size: 0
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - total checked-out connections: 1
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - opening new JDBC connection
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - created connection to: jdbc:oracle:thin:@RCAITMD01:1521:ITMD01, Isolation Level: 2
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - returning connection to pool, pool size: 1
DEBUG net.sf.hibernate.id.TableHiLoGenerator - new hi value: 1
DEBUG net.sf.hibernate.impl.SessionImpl - saving [com.qrs.itm.dao.admin.organization.Organization#22]
DEBUG net.sf.hibernate.transaction.JDBCTransaction - commit
DEBUG net.sf.hibernate.impl.SessionImpl - flushing session
DEBUG net.sf.hibernate.impl.SessionImpl - Flushing entities and processing referenced collections
DEBUG net.sf.hibernate.impl.SessionImpl - Processing unreferenced collections
DEBUG net.sf.hibernate.impl.SessionImpl - Scheduling collection removes/(re)creates/updates
DEBUG net.sf.hibernate.impl.SessionImpl - Flushed: 1 insertions, 0 updates, 0 deletions to 1 objects
DEBUG net.sf.hibernate.impl.SessionImpl - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
DEBUG net.sf.hibernate.impl.SessionImpl - executing flush
DEBUG net.sf.hibernate.persister.EntityPersister - Inserting entity: com.qrs.itm.dao.admin.organization.Organization#22
DEBUG net.sf.hibernate.impl.BatcherImpl - about to open: 0 open PreparedStatements, 0 open ResultSets
DEBUG net.sf.hibernate.impl.SessionFactoryImpl - prepared statement get: insert into QI_ORGANIZATION (ORGANIZATION_NAME, SHORT_NAME, GLN, IS_QRS_CUSTOMER, PARENT_ORGANIZATION_ID, QRS_ACCT_ID, URL, PRIMARY_CONTACT_ID, ORGANIZATION_ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
DEBUG net.sf.hibernate.impl.SessionFactoryImpl - preparing statement
DEBUG net.sf.hibernate.persister.EntityPersister - Dehydrating entity: com.qrs.itm.dao.admin.organization.Organization#22
DEBUG net.sf.hibernate.type.StringType - binding 'name' to parameter: 1
DEBUG net.sf.hibernate.type.StringType - binding null to parameter: 2
DEBUG net.sf.hibernate.type.StringType - binding null to parameter: 3
DEBUG net.sf.hibernate.type.IntegerType - binding '1' to parameter: 4
DEBUG net.sf.hibernate.type.StringType - binding 'ext acct' to parameter: 6
DEBUG net.sf.hibernate.type.StringType - binding null to parameter: 7
DEBUG net.sf.hibernate.util.JDBCExceptionReporter - SQL Exception
java.sql.SQLException: ORA-02291: integrity constraint (SGARCIA_ITM1.QI_ORGANIZATION_FK_1) violated - parent key not found
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:168)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:208)
[snip]
DEBUG net.sf.hibernate.impl.SessionImpl - transaction completion
DEBUG net.sf.hibernate.transaction.JDBCTransaction - rollback
DEBUG net.sf.hibernate.impl.SessionImpl - transaction completion
DEBUG net.sf.hibernate.impl.SessionImpl - closing session
DEBUG net.sf.hibernate.impl.SessionImpl - disconnecting session
DEBUG net.sf.hibernate.connection.DriverManagerConnectionProvider - returning connection to pool, pool size: 2
DEBUG net.sf.hibernate.impl.SessionImpl - transaction completion