Composite Entity update fails
I have a Person object that has a composition with a location object
@ManyToOne(fetch = FetchType.EAGER, cascade =
{ CascadeType.PERSIST, CascadeType.MERGE })
@Cascade(
{org.hibernate.annotations.CascadeType.SAVE_UPDATE })
public Location getLocation()
{
return location;
}
And the Location Entity has a name as Id
@Id
public String getName()
{
return name;
}
I am getting the following exception when Person location changes from L1 to L2 in a Spring MVC form where this Person object is the modelAttribute for the form.
org.springframework.orm.hibernate3.HibernateSystemException: instance id com.xyzLocation has been changed from L2 to L1; Nested Exception - org.hibernate.HibernateException: instance id com.xyzLocation was changed from L2 to L1
source to share
You are misleading Composition with Association .
What you have mapped is an association; composition in Hibernate (JPA) is rendered via annotations @Embeddable
/ @Embedded
. Associations are relationships between separate entities; they are usually related through entity identifiers (foreign keys in the database).
In your specific case, the object Person
points to an object Location
, which means that in the database the PERSONS
table has a foreign key LOCATION_ID
(names may differ) from the table LOCATIONS
. What you are trying to do is update this key on the end Location
, which is illegal because it will break the Hibernate relationship (the other end still has the previous key value inside).
Primary keys usually need to be surrogate and non-updatable to begin with; if you need to "update" it, you will have to either disconnect Location
from Person
, or update Location
, or reassign it, Person
or create a new Location
instance and assign it Person
.
All that said, if you are really trying to model composition relationships, you need to replace @ManyToOne with @Embedded and change the table schema accordingly. Here's a link to the Hibernate Annotation Documentation on Component Mapping .
Also, specifying cascading types in two separate annotations (JPA and Hibernate extension) is not very good. If you really need a Hibernate extension (which you are not doing in this case), just use it and leave the attribute cascade
in the JPA annotation blank.
source to share