JPA2.0:删除OneToMany关系中的实体

发布于 2024-11-01 09:35:03 字数 2440 浏览 3 评论 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);
       }
    }
}

内部专业实体

@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 不起作用。不知道为什么?请帮忙。我需要清除缓存吗?

How do I delete an entity in a 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);
       }
    }
}

Inside Profession Entity

@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;
    }

Then inside my EJB I have this

@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
    }
}

Now addProfession work beautifully, but removeProfession does not work. Not sure why? Help please. Do I need to evict caches?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

污味仙女 2024-11-08 09:35:04

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

我的 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);    

现在在我的托管 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);
}

This is the solution to my original question, however, I do not know if this is the best

My 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);    

Now in my Managed Bean, I do this

/**
 * 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);
}
不弃不离 2024-11-08 09:35:03

如果职业只是此关系的一部分,那么您可以保证当职业从用户集中删除时,通过在关系的 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 节的规则,(因此
没有必要指定
级联=删除
关系)[20]。

If professions are only part of this relationship, then you can guarantee that when a profession is removed from the User's set it will also be removed from the database by turning on orphanRemoval on the OneToMany side of the relationship.

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

This is what the JPA 2.0 specification states

The JPA 2.0 specification states that

Associations that are specified as
OneToOne or OneToMany support use of
the orphanRemoval option. The
following behaviors apply when
orphanRemoval is in effect:

If an entity that is the target of the
relationship is removed from the
relationship (by setting the
relationship to null or removing the
entity from the relationship
collection), the remove operation will
be applied to the entity being
orphaned. The remove operation is
applied at the time of the flush
operation. The orphanRemoval
functionality is intended for entities
that are privately "owned" by their
parent entity. Portable applications
must otherwise not depend upon a
specific order of removal, and must
not reassign an entity that has been
orphaned to another relationship or
otherwise attempt to persist it. If
the entity being orphaned is a
detached, new,or removed entity, the
semantics of orphanRemoval do not
apply.

If the remove operation is applied to
a managed source entity, the remove
operation will be cascaded to the
relationship target in accordance with
the rules of section 3.2.3, (and hence
it is not necessary to specify
cascade=REMOVE for the
relationship)[20].

自在安然 2024-11-08 09:35:03

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

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

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

“eclipselink.persistence-context.persist-on-commit”=“false”

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

My guess as to what is occurring is that your User has a OneToMany relationship to Profession and you user object has the profession. When you delete the Profession the user still has the reference. Because the mapping is cascade persist, it re persists the Profession.

You need to ensure that you remove the profession from the user's professions before deleting it.

If you are using EclipseLink there is a property that may also help, but fixing your code to maintain your model correctly is the best solution. You could also remove the cascade persist.

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

or,
"eclipselink.persistence-context.commit-without-persist-rules"="true"

送舟行 2024-11-08 09:35:03

我刚刚在 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;

I just added orphanRemoval = true in the OneToMany relationship and I resolved it.

Class SolicitudRetorno:

@OneToMany(mappedBy = "solicitud", cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
@NotAudited
private List<RetornoMenor> hijosRetorno;

Class RetornoMenor:

@OneToMany(mappedBy = "solicitud", cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
@NotAudited
private List<RetornoMenor> hijosRetorno;
dawn曙光 2024-11-08 09:35:03

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

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

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

You might try clearing the user field in profession:

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

To be on the safe side, I would also check that the passed in profession's current user equals this, just in case someone passes in a profession belonging to another user.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文