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

Tha*_*ham 6 ejb jpa one-to-many jpa-2.0

如何删除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);
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

内部职业实体

@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;
    }
Run Code Online (Sandbox Code Playgroud)

然后在我的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
    }
}
Run Code Online (Sandbox Code Playgroud)

现在addProfession工作得很漂亮,但removeProfession不起作用.不知道为什么?请帮忙.我需要驱逐缓存吗?

Edw*_*rzo 9

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

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

这就是JPA 2.0规范所述的内容

JPA 2.0规范指出了这一点

指定为OneToOne或OneToMany的关联支持使用orphanRemoval选项.当orphanRemoval生效时,以下行为适用:

如果从关系中删除作为关系目标的实体(通过将关系设置为null或从关系集合中删除实体),则删除操作将应用于要孤立的实体.在刷新操作时应用移除操作.orphanRemoval功能适用于由其父实体私有"拥有"的实体.否则,便携式应用程序必须不依赖于特定的删除顺序,并且不得将已经孤立的实体重新分配给另一个关系或以其他方式尝试保留它.如果孤立的实体是分离的,新的或已删除的实体,则orphanRemoval的语义不适用.

如果将删除操作应用于托管源实体,则删除操作将根据第3.2.3节的规则级联到关系目标(因此没有必要为关系指定cascade = REMOVE)[ 20.


Jam*_*mes 5

我对正在发生的事情的猜测是您的用户与职业有一对多关系,而您的用户对象具有职业。当您删除专业时,用户仍然拥有参考。因为映射是级联持久化的,所以它重新持久化了 Profession。

在删除之前,您需要确保从用户的职业中删除该职业。

如果您正在使用 EclipseLink,则有一个属性也可能有所帮助,但修复您的代码以正确维护您的模型是最好的解决方案。您还可以删除级联持久性。

"eclipselink.persistence-context.persist-on-commit"="false"

或者,“eclipselink.persistence-context.commit-without-persist-rules”="true"


mdm*_*dma 1

您可以尝试清除专业中的用户字段:

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

为了安全起见,我还会检查传入的职业的当前用户是否等于this,以防万一有人传入属于另一个用户的职业。