I have a request table that looks like this (see below for the Hibernate config info and code snippet)...
Code:
CREATE TABLE `request` (
`id` int(11) NOT NULL auto_increment,
`client_id` int(11) default NULL,
`user_id` int(11) default NULL,
`method_id` int(11) default NULL,
`ip_address` varchar(16) NOT NULL default '',
`create_dt` bigint(20) unsigned default NULL,
`mod_dt` bigint(20) unsigned default NULL,
PRIMARY KEY (`id`),
KEY `request_method_id_fk` (`method_id`),
KEY `request_user_id_fk` (`user_id`),
KEY `request_client_id_fk` (`client_id`),
CONSTRAINT `request_client_id_fk` FOREIGN KEY (`client_id`) REFERENCES `client` (`id`),
CONSTRAINT `request_method_id_fk` FOREIGN KEY (`method_id`) REFERENCES `method` (`id`),
CONSTRAINT `request_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB
In the ServiceRequest object, I want to be able to assign a ServiceClient and ServiceUser (for the application to use). When I persist the ServiceRequest, however, I only want the client/user id's to be written to the request table. I do not want Hibernate to try to update the client or user tables (because these should not change in the course of the application and I want to ensure they definitely do not in the database just in case).
However, when I try to flush/close the session I am getting "TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: ServiceUser". I experimented with switching from cascade="none" to cascade="save-delete" and I got ConstraintExceptions because the ServiceClient and ServiceUser already exists in the client and user tables (which means it's trying to update those tables and I don't want that). I also tried marking the ServiceClient and ServiceUser classes as mutable="false" and that didn't work either (same problems as before).
Can anyone suggest what I need to do to make this work?
Hibernate version:
2.1
Code between sessionFactory.openSession() and session.close():
serviceRequest = app.getServiceRequest(); // it is already initialized with a ServiceClient and ServiceMethod
ServiceUser serviceUser = new ServiceUser();
serviceUser.setName("a name");
serviceUser.setClient(serviceRequest.getClient());
serviceRequest.setUser(serviceUser);
session.saveOrUpdate(serviceRequest);
Mapping documents:
<class name="ServiceRequest" table="request">
<id name="id" type="integer" unsaved-value="0">
<generator class="identity"/>
</id>
<property name="ipAddress" column="ip_address"/>
<property name="createMillis" column="create_dt"/>
<property name="modifiedMillis" column="mod_dt"/>
<many-to-one name="client" class="ServiceClient" column="client_id" cascade="none"/>
<many-to-one name="user" class="ServiceUser" column="user_id" cascade="none"/>
<many-to-one name="method" class="ServiceMethod" access="field" column="method_id" cascade="save-update"/>
</class>
<class name="ServiceUser" table="user">
<id name="id" type="integer" unsaved-value="0">
<generator class="identity"/>
</id>
<property name="name" column="name"/>
<many-to-one name="client" class="ServiceClient" column="client_id" cascade="none"/>
</class>
<class name="ServiceClient" table="client">
<id name="id" type="integer" unsaved-value="0">
<generator class="identity"/>
</id>
<property name="name" column="name"/>
<property name="logged" column="is_logged"/>
</class>
Full stack trace of any exception that occurs:
[junit] net.sf.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: ServiceUser
[junit] at net.sf.hibernate.impl.SessionImpl.throwTransientObjectException(SessionImpl.java:2788)
[junit] at net.sf.hibernate.impl.SessionImpl.getEntityIdentifierIfNotUnsaved(SessionImpl.java:2780)
[junit] at net.sf.hibernate.type.EntityType.getIdentifier(EntityType.java:66)
[junit] at net.sf.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:47)
[junit] at net.sf.hibernate.persister.EntityPersister.dehydrate(EntityPersister.java:389)
[junit] at net.sf.hibernate.persister.EntityPersister.update(EntityPersister.java:644)
[junit] at net.sf.hibernate.persister.EntityPersister.update(EntityPersister.java:623)
[junit] at net.sf.hibernate.impl.ScheduledUpdate.execute(ScheduledUpdate.java:52)
[junit] at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2438)
[junit] at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2392)
[junit] at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2260)
Name and version of the database you are using:
MySQL 4.1.x