我正在尝试在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;
}
这是对的吗?
答案 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
实体,例如,要存储与该关系相关的其他数据,则需要声明Event
和Chain
之间的两个一对多关系。