如何使用 JPA 注释创建连接表?

Posted

技术标签:

【中文标题】如何使用 JPA 注释创建连接表?【英文标题】:How to create join table with JPA annotations? 【发布时间】:2011-12-20 05:34:16 【问题描述】:

我需要使用JPA 注释在我的数据库中创建一个连接表,所以结果将是这样的:

到目前为止,我只实现了 2 个实体:

@Entity
@Table(name="USERS", schema="ADMIN")
public class User implements Serializable 

    private static final long serialVersionUID = -1244856316278032177L;
    @Id 
    @Column(nullable = false)
    private String userid;  
    
    @Column(nullable = false)
    private String password;

    public String getUserid() 
        return userid;
    

    public void setUserid(String userid) 
        this.userid = userid;
    

    public String getPassword() 
        return password;
    

    public void setPassword(String password) 
        this.password = password;
    
    


@Entity
@Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable 

    private static final long serialVersionUID = -7274308564659753174L;
    @Id
    @Column(nullable = false)
    private String groupid;
    
    public String getGroupid() 
        return groupid;
    
    public void setGroupid(String groupid) 
        this.groupid = groupid;
    

我应该创建另一个名为USER_GROUP 的实体还是我可以添加一些注释,以便在我从实体(ORM)运行创建表时自动创建连接表?

我应该如何注释我的实体以实现与图像中相同的效果?

【问题讨论】:

组和用户实体之间的基数是什么?是@OneToMany,让每个组有 0..* 用户吗?还是多对多? 它是一个@OneToMany,所以每个组有0..*用户,正如你所说。一个用户必须属于一个并且只属于一个组,但是一个组可以有很多(0.. *) 用户。 【参考方案1】:

要拥有与图表中相同的注释,您可以在 User 类中执行此操作:

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "USER_GROUP", 
           joinColumns =  @JoinColumn(name = "userid") , 
           inverseJoinColumns =  @JoinColumn(name = "groupid") )
private List<Group> grups;

在你的小组课中

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "USER_GROUP", 
           joinColumns =  @JoinColumn(name = "groupid") , 
           inverseJoinColumns =  @JoinColumn(name = "userid") )
private List<User> users;

【讨论】:

为什么是多对多?一个用户必须属于一个并且只属于一个组?但是一个组可以有多个用户。我知道这听起来很罕见,但它必须是那样的。它不像 facebook,用户可以在多个组中,组意味着该用户在系统中的角色。并且一个用户只能拥有一个角色。 问题:如果我已经有了这个额外的表怎么办? JoinTable 不会覆盖existign 吗? @TheWandererr 如果您有现有的表,那么您需要做的是,将名称设置为您的表的名称和连接列的名称。然后 jpa 将使用它。至于覆盖,你的意思是什么?如果实体之间的关系发生变化,那么 jpa 将更改数据库中的数据【参考方案2】:

考虑到我们不能直接访问查询,我想知道以这种方式创建联接表有什么意义? JPA 不允许直接对 Join Table 进行查询,所以如果用户想要对 USER_GROUP 进行操作,他必须在 users 之间创建一个普通的 join 查询和群组;因此,连接表 USER_GROUP 是无用的。

【讨论】:

天使,这就是 JPA 的重点。在这种情况下,您不必为它编写查询,因为所有内容都表示为一个对象。假设您有一个用户实体和一个课程实体。一个用户可以有多个课程,一个课程可以分配给多个用户。 (多对多关系,对吗?)所以您想列出特定用户的课程,该课程在用户实体中定义为变量(可能是列表)。在这种情况下,您只需查找用户,您可以调用列表的 getter(),这将返回他们的课程。可以看到正在使用连接表。【参考方案3】:

您绝对不应该创建 User_Group 实体,因为它更像是底层数据库表示,而不是面向对象的表示。

您可以通过定义如下内容来实现连接表:

@Entity
@Table(name="USERS", schema="ADMIN")
public class User implements Serializable 
//...

@ManyToOne
@JoinTable(name="USER_GROUP")
Group group;

@Entity
@Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable 
//...

@OneToMany(mappedBy="group")
Set<User> users;

编辑:如果要显式设置列的名称,可以使用@JoinColumn 元素,如下所示:

@ManyToOne
@JoinTable(name="USER_GROUP",
    joinColumns = @JoinColumn(name = "userid", 
                              referencedColumnName = "userid"), 
    inverseJoinColumns = @JoinColumn(name = "groupid", 
                              referencedColumnName = "groupid"))
Group group;

【讨论】:

你的意思是@ManyToMany? download.oracle.com/javaee/5/api/javax/persistence/… @Jonathan no 我的意思是@OneToMany@ManyToOne,如示例所示。为什么? @PedroKowalski 不确定,因为它们采用相同的参数,但 @ManyToMany 似乎也表达了他正在寻找的关系。 @Jonatan,不,我不认为它表达了 OP 想要的关系。 “正如你所说,每个组有 0..* 个用户。一个用户必须属于one and just one group,但一个组可以有很多(0..*)个用户。” 问题:如果我已经有了这个额外的表怎么办? JoinTable 不会覆盖existign 吗?【参考方案4】:

我会这样实现:

@Entity
@Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable 
  @OneToMany
  @JoinTable(name = "USER_GROUP",
            joinColumns = @JoinColumn(name = "groupid"),
            inverseJoinColumns = @JoinColumn(name = "userid"))
  private List<User> users;

@PedroKowalski 建议的解决方案也应该有效,但是您必须在 User 实体中保留对 Group 实体的引用,这并不总是可行的。

【讨论】:

嗯,这真的取决于你是想建立单向关系还是双向关系。我假设是双向的,因为用户知道他属于哪个组并且组知道其中有哪些用户似乎是合理的。当然如果需要单向关系,比这个方案也可以。

以上是关于如何使用 JPA 注释创建连接表?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JPA 和 Hibernate 连接两个不相关的实体

如何使用 Spring Data JPA 连接两个表

如何使用连接定义 JPA 存储库查询

如何使用 JPA 和 Hibernate 在非主键上连接表

在哪种情况下使用 JPA @JoinTable 注释?

使用具有一对多关系的 JPA 映射实体,如何添加连接条件