如何在JPA中为自己定义多对多?

时间:2010-11-17 18:43:13

标签: java sql jpa

我正在尝试在JPA中定义这个SQL模式:

TABLE event (id INT)
TABLE chain (predecessor INT, successor INT)

换句话说,每个事件都有许多后继者,这些事件本身就是事件。我试图在JPA中这样做:

@Entity
public class Event {
  @Id Integer id;
  @ManyToMany(cascade = CascadeType.PERSIST)
  @JoinTable(
    name = "chain",
    joinColumns = @JoinColumn(name = "successor"),
    inverseJoinColumns = @JoinColumn(name = "predecessor")
  )
  private Collection<Event> predecessors;
}

@Entity
public class Chain {
  @Id Integer id;
  @ManyToOne(cascade = CascadeType.PERSIST)
  @JoinColumn(name = "predecessor")
  private Event predecessor;
  @ManyToOne(cascade = CascadeType.PERSIST)
  @JoinColumn(name = "successor")
  private Event successor;
}

这是对的吗?

2 个答案:

答案 0 :(得分:1)

通常情况下,既不会使用JoinTable定义ManyToMany,也会将连接表单独定义为自己的实体。通常,连接表不是实体,它们只是连接表,提供商管理它们。当你改变一个或另一个时,你正在为自己创造很多麻烦,只要正确地保持应用程序的内存状态。 (例如,如果您想使用L2缓存,那么这是必要的。)

所以,任何一个都可以正常工作,结合起来,它们有点可乐。通常,如果您将Chain定义为实体,那么您只需要在事件上有一个Chain列表。不会将其重新定义为事件上的JoinTable。这有意义吗?

(并且由于它目前是严格定义的,如果您尝试通过Event上的集合进行更改,它将会中断,除非该ID是数据库生成的序列。)

编辑:类似这样的事情 -

@Entity
public class Event {
  @Id Integer id;

  @OneToMany(cascade = CascadeType.PERSIST, mappedBy="successor")
  private Collection<Chain> predecessorChains;
}

只要您意识到Collection<Event> predecessors本质上是只读的,并且如果您尝试对其进行二级缓存,那么您最初编写的内容就可以正常工作。您在其上放置CascadeType这一事实使您希望能够添加和删除事件,这将在hibernate尝试执行非法SQL时爆炸。

答案 1 :(得分:1)

如果您使用@ManyToMany,则不需要Chain实体(否则,如果您需要Chain实体,例如,要存储与该关系相关的其他数据,则需要声明EventChain之间的两个一对多关系。

相关问题