如何删除OneToMany关系中的实体。
@Entity
@NamedQueries({
@NamedQuery(name="User.findByUserNamePassword",
query="select c from User c where c.userName = :userName AND c.password = :password")
})
@Table(name="\"USER\"")
public class User implements Serializable {
@OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemove=true)
private List<Profession> professions;
public List<Profession> getProfessions() {
return professions;
}
public void setProfessions(List<Profession> professions) {
this.professions = professions;
}
public void addProfession(Profession profession){
if(this.professions == null){
this.professions = new ArrayList<Profession>();
}
this.professions.add(profession);
profession.setUser(this);
}
public void removeProfession(Profession profession){
if(this.professions != null){
professions.remove(profession);
profession.setUser(null);
}
}
}
内部职业实体
@Entity
public class Profession implements Serializable {
@ManyToOne
@JoinColumn(name="UserId", nullable=false)
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
然后在我的EJB中我有这个
@Stateless
@LocalBean
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class ScholarEJB{
/**
* Add a profession to a target user
* @param user
* @param profession
*/
public void addProfession(User user, Profession profession){
//Put the user in a managed state. It is important to do this before
//adding a new profession onto user
user = find(User.class, user.getId());
user.addProfession(profession);
this.create(user); //This is persist action
}
public void removeProfession(User user, Profession profession){
//Put the user in a managed state. It is important to do this before
//adding a new profession onto user
user = find(User.class, user.getId());
user.remove(user);
this.update(user); //merge action
//this.create(user) //also try this as well, but it does not work
}
}
现在addProfession
工作得很漂亮,但removeProfession
不起作用。不知道为什么?请帮忙。我是否需要逐出缓存?
答案 0 :(得分:9)
如果职业只是这种关系的一部分,那么你可以保证当一个职业被从用户的集合中删除时,它也将通过在关系的OneToMany一侧打开orphanRemoval从数据库中删除。
@OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemoval=true)
private List<Profession> professions;
这是JPA 2.0规范陈述的内容
JPA 2.0规范声明
指定为的关联 OneToOne或OneToMany支持使用 orphanRemoval选项。该 以下行为适用于 orphanRemoval生效:
如果一个实体是该目标的 关系被从中移除 关系(通过设置 关系为null或删除 来自关系的实体 集合),删除操作将 适用于实体 而成为孤儿。删除操作是 在冲洗时应用 操作。孤儿撤消 功能适用于实体 他们私下“拥有”的 父实体。便携式应用 否则必须不依赖于 具体的删除顺序,必须 不重新分配已经存在的实体 孤儿或另一种关系孤儿 否则试图坚持下去。如果 孤儿的实体是一个 分离的,新的或删除的实体, orphanRemoval的语义没有 应用
如果应用了删除操作 托管源实体,删除 操作将级联到 关系目标按照 第3.2.3节的规则,(因此 没有必要指定 cascade = REMOVE for 关系)[20]。
答案 1 :(得分:4)
我猜测正在发生的事情是您的用户与专业人士之间存在OneToMany关系,而您的用户对象具有该职业。当您删除专业时,用户仍然具有参考。因为映射是级联持久性的,所以它会持续专业。
在删除之前,您需要确保从用户的职业中移除专业。
如果您使用的是EclipseLink,那么有一个属性可能也有帮助,但修复代码以正确维护模型是最佳解决方案。你也可以删除级联持久性。
“eclipselink.persistence-context.persist上提交”= “假”
,或者 “eclipselink.persistence-context.commit-而不-坚持规则”= “真”
答案 2 :(得分:1)
您可以尝试清除专业中的用户字段:
public void removeProfession(Profession profession){
if(this.professions != null){
professions.remove(profession);
profession.setUser(null); // disassociate profession from user
}
}
为了安全起见,我还会检查传入的职业当前用户是否等于this
,以防万一有人通过属于另一个用户的职业。
答案 3 :(得分:1)
这是我原来问题的解决方案,但是,我不知道这是否是最好的
我的EJB bean
@PersistenceContext(unitName="Bridgeye2-ejbPU")
private EntityManager em;
public <T> T create(T t) {
em.persist(t);
return t;
}
public <T> T find(Class<T> type, Object id) {
return em.find(type, id);
}
public <T> void delete(T t) {
t = em.merge(t);
em.remove(t);
}
public <T> void removeAndClearCaches(T t){
this.delete(t);
clearCaches();
}
public <T> T update(T t) {
return em.merge(t);
现在在我的Managed Bean中,我这样做
/**
* Add a new profession
*/
public void addNewProfession(){
Profession profession = new Profession();
newProfessions.add(profession);
}
/**
* Remove the profession
* @param profession
*/
public void removeProfession(Profession profession){
//This will remove the `profession` of the list
//at the presentation layer
this.myProfessions.remove(profession);
//This will remove the `profession` of the list
//at the persistence layer
scholarEJB.removeAndClearCaches(profession);
}
答案 4 :(得分:0)
我刚刚在OneToMany关系中添加了orphanRemoval = true
,我解决了它。
班级SolicitudRetorno
:
@OneToMany(mappedBy = "solicitud", cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
@NotAudited
private List<RetornoMenor> hijosRetorno;
班级RetornoMenor
:
@OneToMany(mappedBy = "solicitud", cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
@NotAudited
private List<RetornoMenor> hijosRetorno;