调用.delete会删除同一个@OneToMany关联中的所有兄弟记录

时间:2014-10-29 11:46:21

标签: jpa playframework playframework-2.0 one-to-many ebean

我有以下映射:

参数:

public class Parameter extends Model {

    @Id
    public long id;

    @OneToMany(cascade = CascadeType.ALL)
    @OrderBy("parameter DESC")
    public List<Attribute> attributes = new ArrayList<Attribute>();

}

属性:

public class Attribute extends Model {

    @Id
    public long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JsonIgnore
    public Parameter parameter;

}

我在控制器中有一个delete()方法:

public Result deleteAttribute(attributeId) {
    Attribute a = Attribute.find.byId(attributeId);
    if (a == null) {
        return notFound();
    }
    a.delete();
    return ok();
}

调用此方法时,一切正常,属性记录将被删除。但是,属于同一参数的所有其他记录也将被删除

我的映射有什么问题?不应该cascade = CascadeType.ALL意味着删除拥有Parameter会删除属性吗?

1 个答案:

答案 0 :(得分:1)

使用CascadeType.ALLCascadeType.REMOVE时,这是预期的行为。如 JPA 2.0规范(JSR-317)中所述,章节 3.2.3删除

  

如果X是托管实体,则删除操作会使其成为托管实体   除去。删除操作级联到X引用的实体,   如果从X到这些其他实体的关系用注释   cascade=REMOVEcascade=ALL注释元素值。

在您的情况下,Xa表示,因此EntityManager.remove操作会导致a与引用的参数实例一起删除。此外,如果删除了任何引用的参数实例,则级联操作会隐式删除其列表中的相应属性。

旁注:双向关系中缺少mappedBy并未指定所有者(包含FK的关系的拥有方)并导致包含两个外键的其他连接表被视为JPA陷阱

我建议稍微修改一下这种关系,例如:

// Parameter
@OneToMany(mappedBy = "parameter", cascade = ALL) // the non-owning
@OrderBy("parameter DESC")
public List<Attribute> attributes = new ArrayList<Attribute>();

// Attribute
@ManyToOne(cascade = { DETACH, MERGE, PERSIST, REFRESH }) // the owning
@JsonIgnore
public Parameter parameter;

这样只会删除a及其引用的参数实例。