tags:

views:

140

answers:

2

I have Person entity which has composition with Location Entity

@ManyToOne(fetch = FetchType.EAGER, cascade =
{ CascadeType.PERSIST, CascadeType.MERGE })
@Cascade(
{org.hibernate.annotations.CascadeType.SAVE_UPDATE })
public Location getLocation()
{
    return location;
}

And Location Entity has Name as Id

@Id
public String getName()
{
    return name;
}

I am getting following Exception when Person's location is changed from L1 to L2 in Spring MVC form where this Person entity is modelAttribute for the form.

org.springframework.orm.hibernate3.HibernateSystemException:identifier of an instance of com.x.y.z.Location was altered from L2 to L1; nested exception is org.hibernate.HibernateException: identifier of an instance of com.x.y.z.Location was altered from L2 to L1

+1  A: 

You're confusing Composition with Association.

What you have mapped is an association; composition in Hibernate (JPA) is mapped via @Embeddable / @Embedded annotations. Associations are relationships between separate entities; they are usually connected via entity identifiers (foreign keys in the database).

In your particular case, Person entity points to Location entity which means in the database PERSONS table has a LOCATION_ID foreign key (names may differ) to LOCATIONS table. What you're trying to do is to update that key on Location end which is illegal because it would sever Hibernate's relationship (the other end still holds the previous key value internally).

Primary keys should generally be surrogate and not updatable to begin with; if you do need to "update" it you'll have to either disassociate Location from Person, update Location and assign it to Person again OR create a brand new Location instance and assign that to your Person.

All that said, if you're really trying to model Composition relationship, you need to replace @ManyToOne with @Embedded and change your table schema accordingly. Here's a link to Hibernate Annotations documentation on mapping components.

Also, specifying cascade types in two separate annotations (JPA vs Hibernate extension) is not a good thing. If you really need the Hibernate extension one (which you don't in this case), just use it and leave cascade attribute in JPA annotations empty.

ChssPly76
Thank You. it Helped.
Sandip Nakarani
A: 

Hello ChssPly76,

I done same thing in standalone application . The thing works. I think it should be some problem with @modelAttribute.

Sandip Nakarani