I am trying to get a save to cascade through into a CollectionOfElements. I can't get the annotations to work, but I have been able to make it work with a mapping file. I am hoping I am just missing something in my annotations.
I have a Person class who has a Set of ParentChild. ParentChild in turn contains a reference to another Person class. If I create personA, create personB, create a ParentChild, set the reference to the Person in the ParentChild object to personB and then add the ParentChild object to the Set in personA, when saving (actually flushing), I get a TransientObjectException.
I turned logging up to trace and ran with the mapping file and then with annotations and noticed several cascade-related log messages present with the mapping file are missing with annotations.
Mapping file:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"file:c:/dev/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="collectionofelements.Person" table="Person" >
<id name="id" type="long" access="property">
<generator class="common.IncrementMinValueGenerator"/>
</id>
<version name="version" type="long" column="version"/>
<property name="name" access="property" lazy="false"/>
<set name="children" table="ParentChild" cascade="all-delete-orphan">
<key column="parentId" not-null="true"/>
<composite-element class="collectionofelements.ParentChild">
<property name="rank" type="long" not-null="true"/>
<many-to-one name="child" class="collectionofelements.Person"
column="childId" not-null="true" cascade="save-update"/>
</composite-element>
</set>
</class>
</hibernate-mapping>
Person annotations: Code:
package collectionofelements;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;
import javax.persistence.Version;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "Person")
public class Person {
private long id;
private String name;
private long version;
private Set<ParentChild> children = new HashSet<ParentChild>();
@Id
@GenericGenerator(name = "mygen", strategy = "common.IncrementMinValueGenerator")
@GeneratedValue(generator = "mygen")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@CollectionOfElements
@JoinTable(name = "ParentChild", joinColumns = @JoinColumn(name = "parentId"))
@Cascade({ org.hibernate.annotations.CascadeType.ALL,
org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public Set<ParentChild> getChildren() {
return children;
}
public void setChildren(Set<ParentChild> children) {
this.children = children;
}
public void addChild(ParentChild parentChild) {
this.children.add(parentChild);
}
@Version
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
}
ParentChild annotations: Code:
package collectionofelements;
import org.hibernate.annotations.Cascade;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@Embeddable
public class ParentChild {
private Person child;
private long rank;
@ManyToOne(targetEntity = Person.class)
@JoinColumn(name = "childId")
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
public Person getChild() {
return child;
}
public void setChild(Person child) {
this.child = child;
}
public long getRank() {
return rank;
}
public void setRank(long rank) {
this.rank = rank;
}
}
Hibernate version: 3.2.3 GA, ANN 3.3.0 GA
Full stack trace of any exception that occurs:Code:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: collectionofelements.Person
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:397)
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:87)
at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:307)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:755)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1143)
at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:26)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:143)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
Name and version of the database you are using:SQLServer 2005
Trace level Hibernate log excerpt, mapping file:Code:
2007-06-20 21:47:29,524 [main] TRACE org.hibernate.event.def.AbstractFlushingEventListener:58 - flushing session
2007-06-20 21:47:29,539 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener:111 - processing flush-time cascades
2007-06-20 21:47:29,539 [main] TRACE org.hibernate.engine.Cascade:115 - processing cascade ACTION_SAVE_UPDATE for: collectionofelements.Person
2007-06-20 21:47:29,539 [main] TRACE org.hibernate.engine.Cascade:291 - cascade ACTION_SAVE_UPDATE for collection: collectionofelements.Person.children
2007-06-20 21:47:29,539 [main] TRACE org.hibernate.engine.CascadingAction:216 - cascading to saveOrUpdate: collectionofelements.Person
2007-06-20 21:47:29,539 [main] TRACE org.hibernate.event.def.AbstractSaveEventListener:488 - persistent instance of: collectionofelements.Person
2007-06-20 21:47:29,539 [main] TRACE org.hibernate.event.def.DefaultSaveOrUpdateEventListener:99 - ignoring persistent instance
2007-06-20 21:47:29,539 [main] TRACE org.hibernate.event.def.DefaultSaveOrUpdateEventListener:136 - object already associated with session: [collectionofelements.Person#10001]
2007-06-20 21:47:29,539 [main] TRACE org.hibernate.engine.Cascade:306 - done cascade ACTION_SAVE_UPDATE for collection: collectionofelements.Person.children
2007-06-20 21:47:29,539 [main] TRACE org.hibernate.engine.Cascade:150 - done processing cascade ACTION_SAVE_UPDATE for: collectionofelements.Person
2007-06-20 21:47:29,555 [main] TRACE org.hibernate.engine.Cascade:115 - processing cascade ACTION_SAVE_UPDATE for: collectionofelements.Person
2007-06-20 21:47:29,555 [main] TRACE org.hibernate.engine.Cascade:291 - cascade ACTION_SAVE_UPDATE for collection: collectionofelements.Person.children
2007-06-20 21:47:29,555 [main] TRACE org.hibernate.engine.Cascade:306 - done cascade ACTION_SAVE_UPDATE for collection: collectionofelements.Person.children
2007-06-20 21:47:29,555 [main] TRACE org.hibernate.engine.Cascade:150 - done processing cascade ACTION_SAVE_UPDATE for: collectionofelements.Person
2007-06-20 21:47:29,555 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener:154 - dirty checking collections
2007-06-20 21:47:29,555 [main] TRACE org.hibernate.event.def.AbstractFlushingEventListener:171 - Flushing entities and processing referenced collections
2007-06-20 21:47:29,555 [main] DEBUG org.hibernate.engine.Collections:176 - Collection found: [collectionofelements.Person.children#10000], was: [<unreferenced>] (initialized)
2007-06-20 21:47:29,571 [main] DEBUG org.hibernate.engine.Collections:176 - Collection found: [collectionofelements.Person.children#10001], was: [<unreferenced>] (initialized)
2007-06-20 21:47:29,571 [main] TRACE org.hibernate.event.def.AbstractFlushingEventListener:210 - Processing unreferenced collections
2007-06-20 21:47:29,571 [main] TRACE org.hibernate.event.def.AbstractFlushingEventListener:224 - Scheduling collection removes/(re)creates/updates
2007-06-20 21:47:29,571 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener:85 - Flushed: 2 insertions, 0 updates, 0 deletions to 2 objects
2007-06-20 21:47:29,571 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener:91 - Flushed: 2 (re)creations, 0 updates, 0 removals to 2 collections
Trace level Hibernate log excerpt, annotations:Code:
2007-06-20 21:46:58,448 [main] TRACE org.hibernate.event.def.AbstractFlushingEventListener:58 - flushing session
2007-06-20 21:46:58,463 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener:111 - processing flush-time cascades
2007-06-20 21:46:58,463 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener:154 - dirty checking collections
2007-06-20 21:46:58,463 [main] TRACE org.hibernate.event.def.AbstractFlushingEventListener:171 - Flushing entities and processing referenced collections
2007-06-20 21:46:58,463 [main] DEBUG org.hibernate.engine.Collections:176 - Collection found: [collectionofelements.Person.children#10000], was: [<unreferenced>] (initialized)
2007-06-20 21:46:58,463 [main] TRACE org.hibernate.event.def.AbstractFlushingEventListener:210 - Processing unreferenced collections
2007-06-20 21:46:58,479 [main] TRACE org.hibernate.event.def.AbstractFlushingEventListener:224 - Scheduling collection removes/(re)creates/updates
2007-06-20 21:46:58,479 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener:85 - Flushed: 1 insertions, 0 updates, 0 deletions to 1 objects
2007-06-20 21:46:58,479 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener:91 - Flushed: 1 (re)creations, 0 updates, 0 removals to 1 collections