tags:

views:

63

answers:

4

I have a problem with updating related entities.

Let me start with a straightforward example. Suppose I have a User 1:1 Profile relation.

How can I update (replace) Profile entity which belongs to User ?

I have tried the followings without success (both OneToOne relation has CascadeType=ALL property)

em.getTransaction().begin();

1.User.setProfile(Profile)
....
2.User.setProfile(Profile)
Profile.setUser(User)
.....
3.em.remove(User.getProfile())
User.setProfile(Profile)
Profile.setUser(User)

em.getTransaction().commit();

I'm totally confused with JPA, there are some useful example, but they are not about updating entities (just updating single values, raising salary etc ...)

I hope the suggested way will work on in case of 1:N relations as well.

A: 

I always do em.merge(user); after updating entity. That will updated all related entities too, if you have appropriate cascading options.

Now, I know (heard) that entity is supposed to update database itself by the end of transaction, but I prefer having a straight call. And frankly, I find the whole 'auto-updating entity' pattern to be more of a problem than advantage in real-world development.

Nikita Rybak
You shouldn't need to use `em.merge()` unless you have detached entities. All entities in the persistence context will automatically update when the the entity manager is 'flushed', which some (IMO inflexible) frameworks force at the end of every transaction.
Joshua Davis
@Joshua I shouldn't, but this way it works :)
Nikita Rybak
Did you mean this ?Profile.setUser(User);User.setProfile(Profile);em.merge(User);orUser.setProfile(Profile);em.merge(User);they dont work neither ... the new profile is saved, but it could not replace the old one.What did i wrong ?
check them they behave as I said, the new one is created but could not replace the old onehttp://imagebin.org/103055http://imagebin.org/103054
@cscsaba242 Show us your entity mappings, please.
Nikita Rybak
here comeshttp://pastebin.com/THhwrm0S
A: 

It depends on what you want to do. If User and Profile are truly one-to-one, then the whole idea of replacing the whole Profile object with a different one is a little redundant. If you are using a framework which retains the Persistence Context across the entire operation then you can just update the values in the Profile object and flush, as creating new objects will be a bit confusing because of the cascades.

However, if your framework does not keep the Persistence Context around, then you'll have detached entities that have been modified, and you must either use em.merge() or you can get the original entity (em.find) and copy the properties in. IMO, this is tedious, error prone, and unnecessary given a framework that uses JPA properly. It's much better to modify the objects in the Persistence Context and let the 'auto-update entity' thing do it's job (which obviously I'm a big fan of). It takes a little getting used to, but once you get it, you'll never want to go back.

In any case, all the changes will be written out to the JDBC connection when em.flush() is called, and the pending changes in the connection will be committed when the transaction completes.

Joshua Davis
I think I need an example somewhere on the internet.Im using JPA on GAE (I would like to use :)
several terms you mentioned not quite clear in practice, it would be good an example.I copy pasted above the source code of my entities.
A: 

How can I update (replace) Profile entity which belongs to User?

Since your association is bi-directional, you have to manage both sides of the link between User and Profile. So "changing" a user's profile would require something like this:

User user = em.find(User.class, key);

Profile profile = new Profile();
...
user.setProfile(profile);
profile.setUser(user);

em.getTransaction().commit(); 

With the JPA implementation I used, the following query have been performed for the above code:

INSERT INTO CPROFILE (ID) VALUES (?)
    bind => [2]
UPDATE CUSER SET CPROFILE_ID = ? WHERE (ID = ?)
    bind => [2, 1]
Pascal Thivent
Hello Pascal, I have tried this way you mentioned without success, I don't know what is wrong.I'm going to try again, thanksAnd thanks for everyone!
@cscsaba242: That's weird. But I'm not an expert of GAE/J JPA "support", maybe there are some specific details about the behavior I'm not aware of.
Pascal Thivent
A: