JPA2.0:删除OneToMany RelationShip中的实体

时间:2011-04-12 21:46:39

标签: jpa ejb jpa-2.0 one-to-many

如何删除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不起作用。不知道为什么?请帮忙。我是否需要逐出缓存?

5 个答案:

答案 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;