代码之家  ›  专栏  ›  技术社区  ›  yegor256

如何在JPA中定义多对多对自身?

  •  1
  • yegor256  · 技术社区  · 14 年前

    我试图在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 回复  |  直到 14 年前
        1
  •  1
  •   Affe    14 年前

    通常,人们不会同时用join table定义manytomany,然后将jointable单独定义为自己的实体。联接表通常不是实体,它们只是联接表,提供者在hood下管理它们。当您更改应用程序的一个或另一个时,您会给自己带来很多麻烦,因为要正确地维护应用程序的内存状态。(例如,如果要使用二级缓存,则必须使用二级缓存。)

    所以,两种方法都很好,结合起来,它们有点古怪。通常,如果您将链定义为一个实体,那么您只需要在事件上有一个链列表。也不将其重新定义为事件上的Jointable。这有道理吗?

    (正如当前严格定义的那样,如果试图通过事件集合进行更改,则它将中断,除非该ID是数据库生成的序列。)

    编辑:类似这样的-

    @Entity
    public class Event {
      @Id Integer id;
    
      @OneToMany(cascade = CascadeType.PERSIST, mappedBy="successor")
      private Collection<Chain> predecessorChains;
    }
    

    只要你意识到 Collection<Event> predecessors 本质上是只读的,如果尝试二级缓存,它将被释放。事实上你把 CascadeType 在它上面,有一件事是您希望能够向它添加和删除事件,当Hibernate试图执行非法的SQL时,这些事件将会爆炸。

        2
  •  1
  •   axtavt    14 年前

    如果你使用 @ManyToMany 你不需要 Chain 实体(否则,如果需要 例如,实体要存储与关系相关的附加数据,需要声明两个一对多关系 Event )