Ebean.delete()为多对多关系创建错误的SQL

时间:2013-02-10 19:30:08

标签: jpa orm many-to-many ebean

我有两个简单的实体问题标记,以及它们之间的many-to-many关系。一切正常,除非我想使用Ebean.delete(Issue.class, id)删除问题,否则会导致此异常:

javax.persistence.PersistenceException: Query threw SQLException:Unknown column
 'issue_id' in 'where clause' 
Bind values:[1b7e5955c26b51dex546fca27x13cc54c2531x-7fef, ] 
Query was:
select t0.id c0 
from tag t0 
where issue_id=?  

非常奇怪的是,显然生成的SQL是错误的。它尝试访问issue_id表中的tag,但没有。我希望这不是Ebean的错误,而只是我的错误,但我不知道它可能是什么。

以下是实体bean(我删除了getters / setter)和Ebean生成的DDL:

问题实体

@Entity
public class Issue {

    @Id @Column(length=64)
    private String id;    // <-- I use assigned ids
    @Version
    private Date timeStamp;
    private String title;
    private String description;
    private String createdBy;
    @CreatedTimestamp
    private Date createdAt;
    private String state;
    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(
        name="issue_tag",
        joinColumns={@JoinColumn(name="issue_id", referencedColumnName="id")},
        inverseJoinColumns={@JoinColumn(name="tag_id", referencedColumnName="id")})
    private Set<Tag> tags;
}

标记实体

@Entity
public class Tag {

    @Id @Column(length=64)
    private String id;    // <-- I use assigned ids
    @Version
    private Date timeStamp;
    private String name;

    @ManyToMany(mappedBy="tags", cascade=CascadeType.ALL)
    private Set<Issue> issues;
}

生成DDL

create table issue (
  id                        varchar(64) not null,
  title                     varchar(255),
  description               varchar(255),
  created_by                varchar(255),
  state                     varchar(255),
  time_stamp                datetime not null,
  created_at                datetime not null,
  constraint pk_issue primary key (id))
;

create table tag (
  id                        varchar(64) not null,
  name                      varchar(255),
  time_stamp                datetime not null,
  constraint pk_tag primary key (id))
;

create table issue_tag (
  issue_id                       varchar(64) not null,
  tag_id                         varchar(64) not null,
  constraint pk_issue_tag primary key (issue_id, tag_id))
;

alter table issue_tag add constraint fk_issue_tag_issue_01 foreign key (issue_id) references issue (id) on delete restrict on update restrict;

alter table issue_tag add constraint fk_issue_tag_tag_02 foreign key (tag_id) references tag (id) on delete restrict on update restrict;

1 个答案:

答案 0 :(得分:0)

这里的主要问题是你在many-to-many关系上设置删除级联。应仔细进行删除操作的级联。它只应设置在oneone-to-one的{​​{1}}侧。

删除应仅级联到不能单独存在的对象。因此,如果我们有类one-to-many,我们可以在地址列表或与类的关系上设置删除级联和附加信息。 为什么在Person关系上设置删除级联是错误的?想象一下,我们在学生和课程之间有这样的关系。我们已经在两个方向删除了卡斯卡。现在取消一门课程将导致大学所有报名参加此课程的学生退学。删除一名学生会导致取消他所注册的所有课程。

在您的代码中,您在两个关系方向上都有删除级联。事实证明,对于Ebean来说这是一项艰巨的任务。但是假设Ebean完全按照你告诉他的那样做了。这将是一场灾难。为什么呢?

  1. 您正在使用many-to-many
  2. 删除Issue
  3. 删除会级联到与此问题相关的所有标记。
  4. 删除与所有与前一点删除的标签相关的问题级联起来
  5. 回到2。
  6. 因此,如果所有问题和标签都在网络中连接,那么删除其中一个会导致删除整个网络。

    如果您删除这些级联,那么您的代码将正常工作 删除问题将导致:

    • id=1
    • 中删除一行
    • issue表格
    • 中删除相应的行