Debugging Hibernate exceptions for users not so familiar with Hibernate can be frustrating. The following exception is a common source of error:-
Lets try to understand the error with a use case first. The most common scenario when this exception occurs is while trying to save a collection object (but calling save/persist on parent)
Consider the objects Foo has a OneToMany Bars
Foo.java
class Foo {
List bars = new ArrayList();
@OneToMany (mappedBy="foo")
public List<bar> getBars() {
return bars;
}
addBar(Bar bar) {
bars.add(bar)
bar.setFoo(this);
}
}
Bar.java
class Bar {
Foo foo;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn (nullable=false)
public Fund getFoo() {
return this.foo;
}
}
The mapping seems fine and one would expect after adding Bars via addBar (lets say a snappy ui datatable where rows need to be adding dynamically). One could think of adding via addBar() many times and once user is complete and hits on “save”, we could call
entityManager.persist() or hibSession.save() and you are surprised why you got
org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing:
You curse Hibernate and you expect it to save all the children but it didn’t. The solution is, add a cascade to the parent. (unless you want to fire a save every time user adds a row, in which case you should save the bar first)
@OneToMany (mappedBy="foo" cascade=cascade=CascadeType.ALL)
public List<bar> getBars() {
return bars;
}
That’s it. You can now expect hibernate to cascade all persistent operations to it’s children without individually saving each
2 Comments
Hi,
I have a case similar to the above, but even with the cascade set to ALL, i still have the same error. Do you have any other ideas about this?
My getter method looks like this:
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
@JoinColumn(name = “RC_ID”)
public Set getConditionalCriterias() {
final Set conditionalCriterias = new HashSet(); final ConditionalCriteriaCentral condCriteria = new ConditionalCriteriaCentral();
condCriteria.setName(“TEST”);
condCriteria.setValue(“TEST_VALUE”);
conditionalCriterias.add(condCriteria);
return conditionalCriterias;
}
Thanks
What is your persist/save operation? It’s not clear why getConditionalCriterias() is creating a new set every time. Also, while adding a new object to a collection, make sure you are setting the object references both ways. See addBar() method above.
Post a Comment