在 Spring Data JPA 中使用注释连接两个以上的表

Posted

技术标签:

【中文标题】在 Spring Data JPA 中使用注释连接两个以上的表【英文标题】:Join more than two tables using Annotations in Spring Data JPA 【发布时间】:2018-10-01 04:24:03 【问题描述】:

我有三个实体:ABC,它们之间的关系如下:

class A
    @ManyToMany
    List<B> bs;
    //other attributes and getter setters


class B

    @ManyToMany
    List<C> cs;
    //other attributes and getter setters


class C
    //other attributes and getter setters

但是从我当前的实体类中,我可以使用@JoinTable 在任意两个表之间建立关系。但我想要的是将所有 3 个实体之间的关系保存在一个单独的表中,将这些实体的主键作为列。 (外键)

如果我们假设实体BC 已经保存(插入)到数据库中,我插入A 的新实体如下:

A:
  "A_id": 1
  B:[
    "B_id": 1
    
      C:[
          "C_id": 1, "C_id": 2
        ]
    , 
    
      "B_id": 2
      C:[
          "C_id": 2
        ]
     
  ]

那么A应该保存在它的表中,并且关系应该在一个单独的表中列出如下:

A_id    B_id    C_id
=====================
 1       1       1
 1       1       2
 1       2       2

我见过here 的一个相关问题。但我认为我的情况有所不同,因为所有实体ABC 之间存在多对多关系。

我不是要完整的代码。只要能解决目的,任何方法或确切的参考都可以。谢谢

编辑:

我已经尝试实现答案中提到的单独关系表。但是这种方法的问题是,当我从关系表中删除一行时,它也会从BC 的连接表中删除条目。 (影响实体BC之前的关系)

同样在更新行时,它会更改(执行插入)到实体BC 的连接表中。这不是预期的行为。我希望这张表仅用于存储实体之间的关系,而不是用于更改这些实体之间的先前关系。

以下是我的新关系表:

@Entity
@Table(name = "relation_table")
public class RelationEntity 

    @Id
    @Column(name = "pk_relation_id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Integer relatoinId;

    @OneToOne
    @JoinColumn(name = "a_id")
    private A a;

    @OneToOne
    @JoinColumn(name = "b_id")
    private B b;

    @OneToOne
    @JoinColumn(name = "c_id")
    private C c;

    //getter and setters

【问题讨论】:

有什么理由你想要那个?对我来说,这似乎是一个破碎的概念 【参考方案1】:

如果您想将relation 保存在单独的表中,那么您可以简单地执行以下操作来保存primary keys

@Entity
@Table(name = "relation_bridge")
public class RelationBridge 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "a")
    private A a;

    @ManyToOne
    @JoinColumn(name = "b")
    private B b;

    @ManyToOne
    @JoinColumn(name = "c")
    private C c;

    //getters & setters

编辑

当我从关系表中删除一行时,它也会从BC 的连接表中删除条目>。 (影响>entitiesBC之前的关系)

除非明确定义,否则上述解决方案不应delete parent 表中的条目。但是,您可能会在其他类中使用其他映射,因此可以通过在映射中应用 Cascading 来控制此行为。

A Beginner's Guide to JPA and Hibernate Cascade Types

Good read for beginners

【讨论】:

可以说,甚至可以删除代理键,以使每个关联都成为主键的一部分。这样,连接列就会有一个自然的唯一约束。 是的@crizzis,你是对的,但在我的问题中,我也在另一个表中使用了这个表foreign key,还有一些其他的值,然后surrogate key 真的很容易帮助query。这就是为什么我把它留在答案中,因为它也可以帮助读者 @Kaushal28 我提到@ManyToOne不是ManyToMany 这取决于您的问题,您可以保留它ManyToOneOneToOne。考虑到A 是经理,B 是主管,那么ManyToOne 将是更好的选择,因为经理可以领导多个主管。 这种方法的问题是当我从这个关系表中删除条目时,它也会删除我的表BC之间的关系。【参考方案2】:

以及如何将您的新类 RelationEntity 与可空的 A 一起使用。当您打算删除“新”关系时,您会更新它,将 null 放入 A 属性中。这只是一个建议,如果你不能这样做,请原谅。

【讨论】:

以上是关于在 Spring Data JPA 中使用注释连接两个以上的表的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 Spring Data JPA Repository 的 @Query 注释中使用 PostgreSQL 匿名块(PL/pgSQL)?

在Spring Boot应用程序中的模型类中同时使用JPA和MongoDB注释的问题

使用 Spring Data JPA 和 @Query 注释仅获取第一个/最后一个元素

将 @PostFilter 注释应用于通用 Spring Data Jpa 存储库方法

Spring DATA JPA中的关于多表连接的问题

Spring Data JPA 审计不适用于带有 @Modifying 注释的 JpaRepository 更新方法,为啥?