JAVA JPA更新相关实体

时间:2010-06-27 17:54:29

标签: java jpa

我在更新相关实体方面遇到了问题。

让我从一个简单的例子开始。 假设我有一个用户1:1配置文件关系。

如何更新(替换)属于User的个人资料实体?

我尝试了以下但没有成功(OneToOne关系都有CascadeType = ALL属性)

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();

我对JPA感到困惑,有一些有用的例子,但它们不是关于更新实体(只是更新单个值,提高工资等等)。

我希望建议的方式也适用于1:N关系。

4 个答案:

答案 0 :(得分:0)

我在更新实体后总是em.merge(user);。如果您有适当的级联选项,那也将更新所有相关实体。

现在,我知道(听说)实体应该在交易结束时更新数据库本身,但我更喜欢直接调用。坦率地说,我发现整个“自动更新实体”模式更像是一个问题,而不是现实世界中的优势。

答案 1 :(得分:0)

这取决于你想做什么。如果用户和配置文件真正一对一,那么将整个 Profile 对象替换为另一个对象的整个想法有点多余。如果您使用的框架在整个操作中保留了持久性上下文,那么您只需更新 Profile 对象中的值并刷新,因为创建新对象将是由于级联而有点混乱。

但是,如果您的框架没有保留Persistence Context,那么您将拥有已修改的分离实体,并且必须使用em.merge() 才能获得原始实体(em.find)并复制属性.IMO,这是繁琐,容易出错,并且在给定正确使用JPA的框架时是不必要的。修改持久化上下文中的对象并让'自动更新实体'做它的工作(这显然是我的忠实粉丝)要好得多。它需要一点点习惯,但一旦你得到它,你永远不会想回去。

在任何情况下,当调用em.flush()时,所有更改都将写入JDBC连接,并且在事务完成时将提交连接中的挂起更改。

答案 2 :(得分:0)

  

如何更新(替换)属于User的个人资料实体?

由于您的关联是双向的,因此您必须管理UserProfile之间链接的两面。因此,“更改”用户的个人资料需要这样的内容:

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

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

em.getTransaction().commit(); 

使用我使用的JPA实现,已对上面的代码执行了以下查询:

INSERT INTO CPROFILE (ID) VALUES (?)
    bind => [2]
UPDATE CUSER SET CPROFILE_ID = ? WHERE (ID = ?)
    bind => [2, 1]

答案 3 :(得分:0)

我删除了CascadeType ALL,一切都按照我们的预期工作,这里是代码


......................... 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();
    }

谢谢大家!

cscsaba