我有两个实体称为用户和用户配置在我的数据模型。 这里是他们是如何映射。
从用户实体代码:
@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
public UserProfile getUserProfile(){
return this.userProfile;
}
public void setUserProfile(UserProfile userProfile){
this.userProfile=userProfile;
}
代码用户配置实体:
@OneToOne(mappedBy="userProfile",cascade=CascadeType.ALL)
public User getUser(){
return this.user;
}
public void setUser(User user){
this.user=user;
}
正如你看到的,我有一个在用户配置用户属性的cascadetype.all。 但是,当我尝试删除用户配置实体,相应的用户实体仍然停留。 (当我尝试删除用户实体,相应的用户配置实体被删除。)
这里是我的问题: -
你的问题是错误的本身,这是所有的混乱源于。 亚瑟与他的回答一个很好的工作,但它是从评论的混乱仍然存在,所以让我花刺在这里清楚。
做级联持有,只有当我在拥有关系的实体指定它们?
“级联”是你(在双向的情况下,或可能两者)的关系的端部上的一个指定的属性。 它决定了对最终执行的操作将传播到另一端。 有许多不同类型的JPA定义,这些行动更在Hibernate的扩展定义。 这种区别很重要-你应该只说说具体行为一般被传播,而不是“级联”。
PERSIST,MERGE REFRESH传播通常(从它们被宣布到其他的端部)。
REMOVE,然而,是棘手,因为它可能意味着两个不同的东西。 如果你有A和B之间的关系,你想删除 ,你可以删除在另一端B或可以解除关联 ,但留下乙完好无损。 Hibernate会在两者之间有明显的区别-你可以声明删除(删除)和DELETE_ORPHAN
分别级联类型; JPA规范没有。 需要注意的是DELETE_ORPHAN
不支持对单值关系(OneToOne /多对一)。
因此,REMOVE的传播(由本身或当它的所有的一部分)取决于关系是否有明确的所有者(单向总是如此;如果它使用的mappedBy映射,如果它映射不经由连接表双向一样)在这种情况下,它是从拥有者拥有或没有所有者,在这种情况下,它在任何一个方向,但没有传播传播DELETE_ORPHAN
语义,除非被明确指定。 后者的典型例子是双向多到许多。
至于说
当我尝试删除用户配置实体,相应的用户实体仍然停留
也许当你尝试删除你的完整性约束违规从数据库中用户配置 - 你使用MyISAM引擎在MySQL?
但是当你不说一无所知。 也许你的用户配置实体没有一个用户实体的引用。
如在JPA规范说
除去操作级联到由X引用的实体 ,如果从X到这些其他实体的关系被注释与级联= REMOVE或级联= ALL注释元素值
就像是
UserProfile up = entityManager.find(UserProfile.class, id);
entityManager.close();
// Notice User is null outside a persistence context
// So user will be not removed from the database because UserProfile does not have a reference to it
up.setUser(null);
entityManager.getTransaction().begin();
entityManager.remove(up);
entityManager.getTransaction().commit();
或者你有什么样
entityManager.getTransaction().begin();
UserProfile up = entityManager.find(UserProfile.class, id);
// throws UPDATE USER_PROFILE SET USER_ID = NULL
up.setUser(null);
// up.getUser() is null
// So user is not removed
entityManager.remove(up);
entityManager.getTransaction().commit();
为了响应ChhsPly的评论:
在Java持久性与Hibernate的书,您会看到以下
级联属性是有方向性的: 它仅适用于一个协会的结束 。
我认为这将是更好的
它适用于每个操作的关联仅一端
所以,你可以在同一时间放于两侧级联属性,即使是在一个双向的关系。 所以ChssPly是正确的。
mappdeBy属性设置双向关系 。 的mappedBy属性指定的地址实体的关系的逆侧。 这意味着客户的实体是关系的拥有方。
ChssPly是正确的,他说的mappedBy无关与级联
这是正确的,当你有一个双向关系的所有者决定了级联规则,因为它是“老板”。 在“拥有”实体基本上遵循的订单,它不能给订单 - 可以这么说。
随着JPA 2.x中,如果你想级联删除,然后使用orphanRemoval
属性:
@OneToMany(orphanRemoval=true)
检查文档在这里获取更多信息。