Hi,
I have a problem with a one-to-one relationship:
I have two tables: "document" and "reference"
There is a one-to-one relation between both. Each document has only one reference. A reference only references one document. In my application, I have a class called "catalog" which contains a list of references. I cannot change this. An object of type Reference contains the Document object, which it references. A Document doesnt need to know the corresponding Reference object.
This means I have a unidirectional one-to-one relationship between Document and Reference. I modelled this relationship with a unique foreign key association.
The problem is as follows:
I try to save in one transaction, first all Documents and then the References.
The storing of the Documents are working, they get an ID from MySQL. But when hibernate wants to store the Reference Objects, it tries to insert already inserted Documents objects again into the Document table, with too few arguments, only the id. Which is not working, because all columns are defined to be not-null.
I tried everything that came to my mind to get hibernate make an insert into table reference and not to table document again, but with no success.
Hope somebody can help me with this!
Thanks a lot in advance!
Please find below, the table definitions, mappings file and log file excerpt:
I hope thats enough information:
I am using Hibernate 3.2.3.ga
with MySQL 5.0.45 community edition Windows X86
Code:
CREATE TABLE `document` (
`iddocument` INT(10) unsigned NOT NULL AUTO_INCREMENT,
`name` VARCHAR(128) NOT NULL,
`public` TINYINT(1) NULL,
`primary` VARCHAR(128) NOT NULL,
`content` LONGTEXT NOT NULL,
`idbook` INT(10) unsigned NOT NULL,
PRIMARY KEY (`iddocument`),
INDEX `FK_rule_1` (`idbook`),
CONSTRAINT `FK_document_1` FOREIGN KEY `FK_document_1` (`idbook`)
REFERENCES `book` (`idbook`)
ON DELETE CASCADE
ON UPDATE NO ACTION
)
CREATE TABLE `reference` (
`idreference` INT(10) unsigned NOT NULL AUTO_INCREMENT,
`iddocument` INT(10) unsigned NOT NULL,
PRIMARY KEY (`idreference`),
INDEX `FK_reference_1` (`iddocument`),
CONSTRAINT `FK_reference_1` FOREIGN KEY `FK_reference_1` (`iddocument`)
REFERENCES `document` (`iddocument`)
ON DELETE CASCADE
ON UPDATE NO ACTION
)
The mapping file for table document:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Document" table="document" catalog="engine">
<comment></comment>
<id name="id" type="integer">
<column name="iddocument" />
<generator class="native" />
</id>
<property name="name" type="string">
<column name="name" length="128" not-null="true">
</column>
</property>
<many-to-one name="book" column="idbook"
class="Book" not-null="true" cascade="none"/>
<property name="XML" type="string">
<column name="content" not-null="true">
<comment></comment>
</column>
</property>
<property name="primary" type="string">
<column name="primary" length="128" not-null="true">
</column>
</property>
<property name="publicAttribute" type="boolean">
<column name="public" not-null="false">
</column>
</property>
</class>
</hibernate-mapping>
Mapping for table reference:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Reference" table="reference" catalog="engine">
<comment></comment>
<id name="id" type="integer">
<column name="idreference" />
<generator class="native"/>
</id>
<many-to-one name="document" class="Document" column="iddocument" unique="true"/>
</class>
</hibernate-mapping>
Logfile excerpt:
Code:
10:41:21,838 DEBUG AbstractSaveEventListener:153 - saving Reference#<null>]
10:41:21,838 DEBUG AbstractSaveEventListener:244 - executing insertions
10:41:21,838 DEBUG AbstractSaveEventListener:297 - executing identity-insert immediately
10:41:21,838 DEBUG AbstractEntityPersister:2144 - Inserting entity: Reference (native id)
10:41:21,838 DEBUG AbstractBatcher:366 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
10:41:21,838 DEBUG SQL:401 - insert into engine.document (iddocument) values (?)
Hibernate: insert into engine.document (iddocument) values (?)
10:41:21,838 DEBUG AbstractBatcher:484 - preparing statement
10:41:21,838 DEBUG AbstractEntityPersister:1992 - Dehydrating entity: Reference#<null>]
10:41:21,838 DEBUG IntegerType:133 - binding '60' to parameter: 1
10:41:21,854 DEBUG AbstractBatcher:374 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
10:41:21,854 DEBUG AbstractBatcher:533 - closing statement
10:41:21,870 DEBUG JDBCExceptionReporter:69 - could not insert: [Reference] [insert into engine.document (iddocument) values (?)]
java.sql.SQLException: Field 'name' doesn't have a default value
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:946)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3256)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1313)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1585)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1500)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1485)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:73)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:33)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2158)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2638)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:48)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
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:535)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:523)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:519)
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:585)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301)
at $Proxy0.save(Unknown Source)
at Catalog.save(Catalog.java:285)
at Book.save(Book.java:501)
at Store.save(RuleStore.java:353)
at Store.storeBook(RuleStore.java:195)
at test.DBTest.main(DBTest.java:30)
10:41:21,885 WARN JDBCExceptionReporter:77 - SQL Error: 1364, SQLState: HY000
10:41:21,885 ERROR JDBCExceptionReporter:78 - Field 'name' doesn't have a default value
org.hibernate.exception.GenericJDBCException: could not insert: [Reference]
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:40)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2158)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2638)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:48)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
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:535)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:523)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:519)
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:585)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301)
at $Proxy0.save(Unknown Source)
at Catalog.save(Catalog.java:285)
at Book.save(Book.java:501)
at Store.save(Store.java:353)
at Store.storeBook(Store.java:195)
at test.DBTest.main(DBTest.java:30)
Caused by: java.sql.SQLException: Field 'name' doesn't have a default value
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:946)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3256)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1313)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1585)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1500)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1485)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:73)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:33)
... 26 more
10:41:21,885 DEBUG ThreadLocalSessionContext:300 - allowing proxied method [isOpen] to proceed to real session
10:41:21,885 DEBUG ThreadLocalSessionContext:300 - allowing proxied method [close] to proceed to real session
10:41:21,885 DEBUG SessionImpl:273 - closing session
10:41:21,885 DEBUG ConnectionManager:380 - performing cleanup
10:41:21,885 DEBUG ConnectionManager:441 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
10:41:21,885 DEBUG DriverManagerConnectionProvider:129 - returning connection to pool, pool size: 1