Reputation: 80166
I have a Product class which has a 1-to-many association to itself (composite pattern). Below are the pojo, hbm, test code and log/error respectively. Can someone explain what this error is about. Why am I getting this error when setting the parent's primary key?
Product pojo
public class Product
{
private Long id;
private Set<Product> children = Collections.emptySet();
public void addChild(final Product child)
{
if (children.isEmpty())
{
children = Sets.newHashSet();
}
child.setParent(this);
children.add(child);
}
}
hbm.xml
<class name="Product" table="PRODUCT">
<set name="children" lazy="false" table="PRODUCT">
<key>
<column name="ID" />
</key>
<one-to-many class="Product" />
</set>
</class>
Test
public void save()
{
// Level 1 - mortgage LOB
Product mortgage = new Product();
mortgage.setCode("Mortgage");
Product ml = new Product();
ml.setCode("Mortgage Loan");
Product me = new Product();
me.setCode("Home Equity LOC");
//Level 2
mortgage.addChild(ml);
mortgage.addChild(me);
hibernateTemplate.save(mortgage);
}
log and error
DEBUG [org.hibernate.SQL] insert into PRODUCT (ID, CODE, NAME, STARTDATE, ENDDATE, ISDECISIONABLE, ISSELECTABLE) values (null, ?, ?, ?, ?, ?, ?)
DEBUG [org.hibernate.type.StringType] binding 'Mortgage' to parameter: 1
DEBUG [org.hibernate.type.StringType] binding null to parameter: 2
DEBUG [org.hibernate.type.TimestampType] binding null to parameter: 3
DEBUG [org.hibernate.type.TimestampType] binding null to parameter: 4
DEBUG [org.hibernate.type.BooleanType] binding 'false' to parameter: 5
DEBUG [org.hibernate.type.BooleanType] binding 'false' to parameter: 6
DEBUG [org.hibernate.SQL] call identity()
DEBUG [org.hibernate.SQL] update PRODUCT set ID=? where ID=?
DEBUG [org.hibernate.type.LongType] binding '1' to parameter: 1
ERROR [org.hibernate.event.def.AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.Product
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:78)
Upvotes: 1
Views: 1983
Reputation: 33
well I don't think that is all your code rigth? because in your pojo you need to have getters and setters for your Set. And try to saveyour Product this way:
Set children=new HashSet();
Product p=new Product();
Product p1=new Product();
Product p2=new Product();
children.add(p1);
children.add(p2);
p.setChildren(children);
hibernateTemplate.save(p);
But put cascade="all" or cascade="save-update" in your set mapping.
Upvotes: 0
Reputation: 120168
A transient object is one that has not been saved. As mapped, your relationship does not use any 'transitive persistence', that is to say, you have not told hibernate that when you save the parent you want to save the children. I guess the error is because you have instances of the children (doesn't matter that the children have the same class of the parent) on the parent (in the session), and hibernate is aware of that, but it doesn't know what to do with them.
You can either:
1) save the children before saving the parent
2) add the 'cascade' attribute to your mapping, something like cascade="save" or cascade="all"
see http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-transitive
Upvotes: 4