2011-04-12 70 views
6

如何删除OneToMany关系中的实体。JPA2.0:删除OneToMany RelationShip中的实体

@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

在你的一对多的关系,正确的注释是orphanRemoval =真的,不是orphanRemove =真 – greuze 2011-08-10 08:25:48

回答

1

你可以尝试清除在行业用户领域:

public void removeProfession(Profession profession){ 
     if(this.professions != null){ 
      professions.remove(profession); 
      profession.setUser(null); // disassociate profession from user 
     } 
    } 

为了安全起见,我还要检查在行业的当前用户通过等于this,以防万一有人经过的职业属于另一个用户。

+0

尝试为好,不能正常工作。在我删除之后,在我坚持/合并之前,我打印出专业列表,列表恢复正确。但是当我坚持/合并,这并不反映在我的数据库 – 2011-04-12 22:22:06

9

如果职业只是这种关系的一部分,那么你可以保证,当一个职业从用户的设置中删除时,它也将通过在关系的OneToMany侧打开orphanRemoval从数据库中删除。

@OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemoval=true) 
private List<Profession> professions; 

这是JPA 2.0规范状态

的JPA 2.0规范规定什么被指定为 OneToOne或一对多支持使用 的orphanRemoval选项

协会。当 orphanRemoval是生效的 应用以下行为:

如果是 关系的目标的实体从 关系移除(通过从关系 设置 关系为空或去除 实体收集),删除操作将 应用于实体 成为孤儿。删除操作是在冲洗 操作时应用的 。孤立删除 功能适用于实体 ,这些实体由其 父实体私有“拥有”。便携式应用程序 必须不依赖 删除的特定顺序,并且必须 不会重新分配已被其他关系孤立的实体或 否则会尝试保留它。如果 孤立的实体是 分离的,新的或移除的实体,则应用odphanRemoval的语义 。

如果删除操作被施加到一个 管理的源实体,所述删除 操作将按照第3.2节的 规则级联到 关系目标。3,(因此 没有必要指定 cascade = REMOVE为 关系)[20]。

+1

可悲的是我尝试它,但仍然无法正常工作。但我找出了什么工作。我必须清除二级缓存才能工作。专业= em.merge(职业); em.remove(职业); em.getEntityManagerFactory()。getCache()。evictAll();',这项工作,但我不确定这是否是最好的方法 – 2011-04-12 23:29:05

+0

你的文章可以发布你的更新方法吗?它表示它进行了合并,这在目前的代码中并不清楚或明显。 – 2011-04-12 23:48:45

+0

我转发我的代码。请检查出 – 2011-04-13 00:04:23

1

这是解决我原来的问题,但是,我不知道这是不是最好的

我EJB豆

@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

我的猜测是你的用户与专业有一对多的关系,而你的用户对象有专业。当你删除职业时,用户仍然有参考。因为映射是级联的,所以它继续存在职业。

您需要确保在删除用户职业之前将其从职业中​​删除。

如果您使用的是EclipseLink,有一个属性可能也有帮助,但修复代码以正确维护模型是最佳解决方案。你也可以删除cascade persist。

“eclipselink.persistence-context.persist上提交”= “假”

,或者 “eclipselink.persistence-context.commit - 没有 - 坚持规则”= “真”

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;