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 to 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 its children without individually saving each
5 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.
Thanks buddy, you helped me to resolve my problem.
I have two tables which has the following structure
@hibernate.class table = “Person”
class Person{
private String name
private Car car
@hibernate.id column = “NAME” generator-class = “native”
@hibernate.generator-param name = “sequence” value = “SEQ_1″
public String getName(){return name;}
public void setName(String name){this.name=name;}
@hibernate.many-to-one column=”MODEL_ID” class=”CAR” cascade=”all”
public Car getCar(){return car;}
public void setCar(Car car){this.car=car;}
}
@hibernate.class table = “CAR”
class Car{
private String modelID;
private String carName;
@hibernate.id column = “MODEL_ID” generator-class = “assigned”
public String getModelID(){return modelID}
etc….
}
but when i try to delete or save on the Person class it hiberbate throws this exception
org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing:
Can you give me any help on this?
Thank you so much!
Post a Comment