我在更新相关实体方面遇到了问题。
让我从一个简单的例子开始。 假设我有一个用户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关系。
答案 0 :(得分:0)
我在更新实体后总是em.merge(user);
。如果您有适当的级联选项,那也将更新所有相关实体。
现在,我知道(听说)实体应该在交易结束时更新数据库本身,但我更喜欢直接调用。坦率地说,我发现整个“自动更新实体”模式更像是一个问题,而不是现实世界中的优势。
答案 1 :(得分:0)
这取决于你想做什么。如果用户和配置文件真正一对一,那么将整个 Profile 对象替换为另一个对象的整个想法有点多余。如果您使用的框架在整个操作中保留了持久性上下文,那么您只需更新 Profile 对象中的值并刷新,因为创建新对象将是由于级联而有点混乱。
但是,如果您的框架没有保留Persistence Context,那么您将拥有已修改的分离实体,并且必须使用em.merge()
或才能获得原始实体(em.find
)并复制属性.IMO,这是繁琐,容易出错,并且在给定正确使用JPA的框架时是不必要的。修改持久化上下文中的对象并让'自动更新实体'做它的工作(这显然是我的忠实粉丝)要好得多。它需要一点点习惯,但一旦你得到它,你永远不会想回去。
在任何情况下,当调用em.flush()
时,所有更改都将写入JDBC连接,并且在事务完成时将提交连接中的挂起更改。
答案 2 :(得分:0)
如何更新(替换)属于User的个人资料实体?
由于您的关联是双向的,因此您必须管理User
和Profile
之间链接的两面。因此,“更改”用户的个人资料需要这样的内容:
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