开发者

JAVA JPA updating the related entities

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.


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.


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.


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]


I removed the CascadeType ALL, and everything works as we expected, here comes the code


......................... CPROFILE
@Entity
public class CProfile {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Key id;
        private String phone;

    @OneToOne(mappedBy="profile")
    private CUser User;

......................... CUSER @Entity public class CUser { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Key id; private String email;

@OneToMany(mappedBy="user")
private List<CPossibility> Possibilities = new ArrayList<CPossibility>();

@OneToOne 
@JoinColumn(name="cprofile_id") 
private CProfile profile;   

......................... CREATE ... CUser User = em.find(CUser.class, UserId_); ...
em.getTransaction().begin(); try { Profile_.setUser(User); User.setProfile(Profile_);

        em.persist(Profile_);

        em.getTransaction().commit();
    }
    catch(Exception e){GAEHelper.getLogger().warning("Exception:"+e.getMessage()+" "+e.getCause());}        
    finally {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
    }

    em.close();

    return true;
}

......................... UPDATE
... CUser User = em.find(CUser.class, UserId_); ... em.getTransaction().begin(); try { em.remove(User.getProfile());

        Profile_.setUser(User);             
        User.setProfile(Profile_);

        em.persist(Profile_);
        em.getTransaction().commit();
    }

Thanks Guys !

cscsaba

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜