OK, I have simplified my code and mapping files down to the bare minimum to reproduce the problem. I also tried running on PostgreSQL as well as SQL Server. It turns out that the exception DOESN'T occur on PostgreSQL, but DOES on SQL Server. Here are my simplified mapping files:
Code:
<class
name="com.nathan.hibernatetest.UUIDTable"
table="uuidtable"
schema="nathan">
<id
name="UUIDTable_UUID"
column="uuidtable_uuid"
type="java.lang.String"
length="36">
<generator
class="com.nathan.hibernatetest.HibernateUuidGenerator" />
</id>
</class>
<class
name="com.nathan.hibernatetest.OneToOneTable"
table="onetoonetable"
schema="nathan">
<id
name="OneToOneTableId"
column="onetoonetable_id"
type="java.lang.Long">
<generator class="native" />
</id>
<many-to-one
name="UUIDTable"
class="com.nathan.hibernatetest.UUIDTable"
unique="true"
cascade="all">
<column
name="uuidtable_uuid"
not-null="true"
unique="true" />
</many-to-one>
</class>
Here is the code I am running:
Code:
try {
Session s = sf.openSession();
Transaction t = s.beginTransaction();
OneToOneTable onetooneclass = new OneToOneTable();
UUIDTable uuidclass = new UUIDTable();
onetooneclass.setUUIDTable(uuidclass);
s.save(onetooneclass);
t.commit();
s.close();
} catch (Exception e) {
e.printStackTrace();
throw e;
}
Here is what running on PostgreSQL produces in the log (SUCCESS):
Quote:
3897 DEBUG [main] impl.SessionImpl - opened session at timestamp: 4606868032831488
3912 DEBUG [main] transaction.JDBCTransaction - begin
3912 DEBUG [main] jdbc.ConnectionManager - opening JDBC connection
3912 DEBUG [main] transaction.JDBCTransaction - current autocommit status: false
3912 DEBUG [main] jdbc.JDBCContext - before transaction completion
3912 DEBUG [main] def.DefaultSaveOrUpdateEventListener - saving transient instance
3912 DEBUG [main] jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
3912 DEBUG [main] hibernate.SQL - select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
3912 DEBUG [main] jdbc.AbstractBatcher - preparing statement
3959 DEBUG [main] id.SequenceGenerator - Sequence identifier generated: 1
3959 DEBUG [main] jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
3959 DEBUG [main] jdbc.AbstractBatcher - closing statement
3959 DEBUG [main] def.AbstractSaveEventListener - generated identifier: 1, using strategy: org.hibernate.id.SequenceGenerator
3959 DEBUG [main] def.AbstractSaveEventListener - saving [com.nathan.hibernatetest.OneToOneTable#1]
3990 DEBUG [main] engine.Cascade - processing cascade ACTION_SAVE_UPDATE for: com.nathan.hibernatetest.OneToOneTable
3990 DEBUG [main] engine.CascadingAction - cascading to saveOrUpdate: com.nathan.hibernatetest.UUIDTable
3990 DEBUG [main] def.AbstractSaveEventListener - transient instance of: com.nathan.hibernatetest.UUIDTable
3990 DEBUG [main] def.DefaultSaveOrUpdateEventListener - saving transient instance
4240 DEBUG [main] def.AbstractSaveEventListener - generated identifier: 5e938180-131f-11da-9c03-7b6586cbaab8, using strategy: com.nathan.hibernatetest.HibernateUuidGenerator
4240 DEBUG [main] def.AbstractSaveEventListener - saving [com.nathan.hibernatetest.UUIDTable#5e938180-131f-11da-9c03-7b6586cbaab8]
4255 DEBUG [main] engine.Cascade - done processing cascade ACTION_SAVE_UPDATE for: com.nathan.hibernatetest.OneToOneTable
4255 DEBUG [main] engine.Cascade - processing cascade ACTION_SAVE_UPDATE for: com.nathan.hibernatetest.OneToOneTable
4255 DEBUG [main] engine.Cascade - done processing cascade ACTION_SAVE_UPDATE for: com.nathan.hibernatetest.OneToOneTable
4255 DEBUG [main] transaction.JDBCTransaction - commit
4255 DEBUG [main] impl.SessionImpl - automatically flushing session
4255 DEBUG [main] def.AbstractFlushingEventListener - flushing session
4255 DEBUG [main] def.AbstractFlushingEventListener - processing flush-time cascades
4271 DEBUG [main] engine.Cascade - processing cascade ACTION_SAVE_UPDATE for: com.nathan.hibernatetest.OneToOneTable
4271 DEBUG [main] engine.CascadingAction - cascading to saveOrUpdate: com.nathan.hibernatetest.UUIDTable
4271 DEBUG [main] def.AbstractSaveEventListener - persistent instance of: com.nathan.hibernatetest.UUIDTable
4271 DEBUG [main] def.DefaultSaveOrUpdateEventListener - ignoring persistent instance
4271 DEBUG [main] def.DefaultSaveOrUpdateEventListener - object already associated with session: [com.nathan.hibernatetest.UUIDTable#5e938180-131f-11da-9c03-7b6586cbaab8]
4271 DEBUG [main] engine.Cascade - done processing cascade ACTION_SAVE_UPDATE for: com.nathan.hibernatetest.OneToOneTable
4271 DEBUG [main] def.AbstractFlushingEventListener - dirty checking collections
4271 DEBUG [main] def.AbstractFlushingEventListener - Flushing entities and processing referenced collections
4271 DEBUG [main] def.AbstractFlushingEventListener - Processing unreferenced collections
4271 DEBUG [main] def.AbstractFlushingEventListener - Scheduling collection removes/(re)creates/updates
4271 DEBUG [main] def.AbstractFlushingEventListener - Flushed: 2 insertions, 0 updates, 0 deletions to 2 objects
4271 DEBUG [main] def.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
4271 DEBUG [main] pretty.Printer - listing entities:
4271 DEBUG [main] pretty.Printer - com.nathan.hibernatetest.UUIDTable{UUIDTable_UUID=5e938180-131f-11da-9c03-7b6586cbaab8}
4271 DEBUG [main] pretty.Printer - com.nathan.hibernatetest.OneToOneTable{OneToOneTableId=1, UUIDTable=com.nathan.hibernatetest.UUIDTable#5e938180-131f-11da-9c03-7b6586cbaab8}
4286 DEBUG [main] def.AbstractFlushingEventListener - executing flush
4286 DEBUG [main] entity.AbstractEntityPersister - Inserting entity: [com.nathan.hibernatetest.UUIDTable#5e938180-131f-11da-9c03-7b6586cbaab8]
4286 DEBUG [main] jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
4286 DEBUG [main] hibernate.SQL - insert into nathan.uuidtable (uuidtable_uuid) values (?)
Hibernate: insert into nathan.uuidtable (uuidtable_uuid) values (?)
4286 DEBUG [main] jdbc.AbstractBatcher - preparing statement
4286 DEBUG [main] entity.AbstractEntityPersister - Dehydrating entity: [com.nathan.hibernatetest.UUIDTable#5e938180-131f-11da-9c03-7b6586cbaab8]
4286 DEBUG [main] type.StringType - binding '5e938180-131f-11da-9c03-7b6586cbaab8' to parameter: 1
4286 DEBUG [main] jdbc.AbstractBatcher - Adding to batch
4286 DEBUG [main] entity.AbstractEntityPersister - Inserting entity: [com.nathan.hibernatetest.OneToOneTable#1]
4286 DEBUG [main] jdbc.AbstractBatcher - Executing batch size: 1
4302 DEBUG [main] jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
4302 DEBUG [main] jdbc.AbstractBatcher - closing statement
4302 DEBUG [main] jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
4302 DEBUG [main] hibernate.SQL - insert into nathan.onetoonetable (uuidtable_uuid, onetoonetable_id) values (?, ?)
Hibernate: insert into nathan.onetoonetable (uuidtable_uuid, onetoonetable_id) values (?, ?)
4318 DEBUG [main] jdbc.AbstractBatcher - preparing statement
4318 DEBUG [main] entity.AbstractEntityPersister - Dehydrating entity: [com.nathan.hibernatetest.OneToOneTable#1]
4318 DEBUG [main] type.StringType - binding '5e938180-131f-11da-9c03-7b6586cbaab8' to parameter: 1
4318 DEBUG [main] type.LongType - binding '1' to parameter: 2
4318 DEBUG [main] jdbc.AbstractBatcher - Adding to batch
4318 DEBUG [main] jdbc.AbstractBatcher - Executing batch size: 1
4333 DEBUG [main] jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
4333 DEBUG [main] jdbc.AbstractBatcher - closing statement
4333 DEBUG [main] def.AbstractFlushingEventListener - post flush
4333 DEBUG [main] jdbc.JDBCContext - before transaction completion
4333 DEBUG [main] impl.SessionImpl - before transaction completion
4349 DEBUG [main] transaction.JDBCTransaction - committed JDBC Connection
4349 DEBUG [main] jdbc.JDBCContext - after transaction completion
4349 DEBUG [main] impl.SessionImpl - after transaction completion
4349 DEBUG [main] impl.SessionImpl - closing session
4364 DEBUG [main] jdbc.ConnectionManager - closing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
4364 DEBUG [main] jdbc.JDBCContext - after transaction completion
4364 DEBUG [main] impl.SessionImpl - after transaction completion
Here is what running on SQL Server produces in the log (FAILURE):
Quote:
3648 DEBUG [main] impl.SessionImpl - opened session at timestamp: 4606870134833152
3648 DEBUG [main] transaction.JDBCTransaction - begin
3648 DEBUG [main] jdbc.ConnectionManager - opening JDBC connection
3648 DEBUG [main] transaction.JDBCTransaction - current autocommit status: false
3648 DEBUG [main] jdbc.JDBCContext - before transaction completion
3663 DEBUG [main] def.DefaultSaveOrUpdateEventListener - saving transient instance
3663 DEBUG [main] def.AbstractSaveEventListener - saving [com.nathan.hibernatetest.OneToOneTable#<null>]
3663 DEBUG [main] def.AbstractSaveEventListener - executing insertions
3663 DEBUG [main] engine.Cascade - processing cascade ACTION_SAVE_UPDATE for: com.nathan.hibernatetest.OneToOneTable
3663 DEBUG [main] engine.CascadingAction - cascading to saveOrUpdate: com.nathan.hibernatetest.UUIDTable
3679 DEBUG [main] def.AbstractSaveEventListener - transient instance of: com.nathan.hibernatetest.UUIDTable
3679 DEBUG [main] def.DefaultSaveOrUpdateEventListener - saving transient instance
3912 DEBUG [main] def.AbstractSaveEventListener - generated identifier: 9079e6cc-1320-11da-bbbf-5d2f1a787932, using strategy: com.nathan.hibernatetest.HibernateUuidGenerator
3912 DEBUG [main] def.AbstractSaveEventListener - saving [com.nathan.hibernatetest.UUIDTable#9079e6cc-1320-11da-bbbf-5d2f1a787932]
3928 DEBUG [main] engine.Cascade - done processing cascade ACTION_SAVE_UPDATE for: com.nathan.hibernatetest.OneToOneTable
org.hibernate.PropertyValueException: not-null property references a null or transient value: com.nathan.hibernatetest.OneToOneTable.UUIDTable
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:265)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:167)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:101)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:516)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:506)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:502)
at UUIDTableTest.testOne(UUIDTableTest.java:90)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
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 junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
I am using Hibernate Tools to generate my java classes, and SchemaExport to generate my database tables. I ran all of this on the latest code (Hibernate 3.1 and Tools) from CVS.
Here are my classes:
OneToOneTable.java:
Code:
package com.nathan.hibernatetest;
import java.util.*;
/**
* OneToOneTable generated by hbm2java
*/
public class OneToOneTable implements java.io.Serializable {
// Fields
private Long OneToOneTableId;
private UUIDTable UUIDTable;
// Constructors
/** default constructor */
public OneToOneTable() {
}
/** constructor with id */
public OneToOneTable(Long OneToOneTableId) {
this.OneToOneTableId = OneToOneTableId;
}
// Property accessors
/**
*
*/
public Long getOneToOneTableId() {
return this.OneToOneTableId;
}
public void setOneToOneTableId(Long OneToOneTableId) {
this.OneToOneTableId = OneToOneTableId;
}
/**
*
*/
public UUIDTable getUUIDTable() {
return this.UUIDTable;
}
public void setUUIDTable(UUIDTable UUIDTable) {
this.UUIDTable = UUIDTable;
}
}
UUIDTable.java:
Code:
package com.nathan.hibernatetest;
import java.util.*;
/**
* UUIDTable generated by hbm2java
*/
public class UUIDTable implements java.io.Serializable {
// Fields
private String UUIDTable_UUID;
// Constructors
/** default constructor */
public UUIDTable() {
}
/** constructor with id */
public UUIDTable(String UUIDTable_UUID) {
this.UUIDTable_UUID = UUIDTable_UUID;
}
// Property accessors
/**
*
*/
public String getUUIDTable_UUID() {
return this.UUIDTable_UUID;
}
public void setUUIDTable_UUID(String UUIDTable_UUID) {
this.UUIDTable_UUID = UUIDTable_UUID;
}
}
Here is the DDL for SQL Server:
Code:
create table nathan.onetoonetable (onetoonetable_id numeric(19,0) identity not null, uuidtable_uuid varchar(36) not null unique, primary key (onetoonetable_id));
create table nathan.uuidtable (uuidtable_uuid varchar(36) not null, primary key (uuidtable_uuid));
alter table nathan.onetoonetable add constraint FKEACC67899F4052C3 foreign key (uuidtable_uuid) references nathan.uuidtable;
And here is the DDL for PostgreSQL:
Code:
create table nathan.onetoonetable (onetoonetable_id int8 not null, uuidtable_uuid varchar(36) not null unique, primary key (onetoonetable_id));
create table nathan.uuidtable (uuidtable_uuid varchar(36) not null, primary key (uuidtable_uuid));
alter table nathan.onetoonetable add constraint FKEACC67899F4052C3 foreign key (uuidtable_uuid) references nathan.uuidtable;
create sequence hibernate_sequence;
I plan on submitting this to JIRA as a bug unless someone can point out my problem. Thanks in advance for any help!
Nathan