Hibernate(以及 JPA)中,@JoinColumn@JoinTable 都用于定义实体类之间的关联关系,但它们的使用场景和实现方式不同:

一句话总结:

  • @JoinColumn外键字段在本表或关联实体对应的表中
  • @JoinTable通过一个中间表(关联表)建立关系,常用于多对多或特定一对多/多对一情况。

详细区别

特性@JoinColumn@JoinTable
使用场景一对一 (@OneToOne)、多对一 (@ManyToOne)、有时用于一对多多对多 (@ManyToMany),也可以用于一对多等
外键存放位置外键字段直接存储在实体的表中需要额外的中间表来存储关联关系
数据库结构没有中间表生成一个中间表,表中含两个外键列
示例用户表有一个 address_id 外键指向地址表用户与角色通过一个 user_role 中间表关联

示例代码

使用 @JoinColumn(一对一)

@Entity
public class User {
    @Id
    private Long id;

    @OneToOne
    @JoinColumn(name = "address_id") // 外键字段
    private Address address;
}

数据库表结构:user 表中有 address_id 外键列。

使用 @JoinTable(多对多)

@Entity
public class User {
    @Id
    private Long id;

    @ManyToMany
    @JoinTable(
        name = "user_role", // 中间表名
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> roles;
}

数据库会生成一个 user_role 中间表,包含两个字段:user_idrole_id,分别关联到 user 表和 role 表。

总结建议

  • 只要你能通过一个外键字段搞定的关系,用 @JoinColumn 就够了;
  • 如果两个实体之间是 多对多 或你想自定义一个复杂中间表(带时间戳、标志位等),就用 @JoinTable