JPA 中 @JoinColumn 的 name 和 referencedColumnName 属性怎么辨别

一、@JoinColumn

@JoinColumn 的作用就是声明关联关系的,什么是关联关系?

就是我们在数据库设计时常说的一对多、多对一、多对多关系。因此,@JoinColumn 必须和这些关系注解一起使用,否则是没有意义的。

二、name 和 referencedColumnName

刚开始接触这两个属性会觉得很难理解,特别是看书的时候总是分不清,看下面的例子:

// Address表对应的Entity
Class Address{
	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long addressID;
    ...
}

// User表对应的Entity
Class User{
	...
	// 显然下面这个属性表示每个User对应一个Address,思考一下:
	// 平时我们在设计数据库的时候会怎么处理这种关系?我一般对这
	// 一对一的关系,都会直接在User表中添加一个字段指向Address
	// 的主键,而下面注解确实是这样做的。
 	@OneToOne
    @JoinColumn(name = "addressID", referencedColumnName = "id")
    private Address address;
    ...
}

其实这两个属性指向的都是数据库字段,也就是数据库里面真真实实存在的表的字段,而不是我们在Java程序中的成员变量名(重要)。

如上面的代码,它表示在User表中添加一个addressID字段,这个字段的取值就是 Address 表的 id,也就是主键,也就说明了它通过这个字段关联着两张表(重要,重要,重要),这其实就是我们在学习数据库时处理一对一关系的一种方法,是不是很熟悉?

所以,一定记住,两个属性都是指数据库里的字段!!!!

  • name:当前表的字段
  • referencedColumnName:引用表对应的字段,如果不注明,默认就是引用表的主键

实际上数据库中的表结构如下, User 的 addressID 字段关联着 Address 的 id 字段:

User 表属性语义
id主键
addressID关联 Address 表主键
name姓名
phone手机
其他属性
Address 表属性语义
id主键
receiver收件人
detail详细地址
其他属性

看了上面的表是不是就很清楚了?

很多网上的解释说 name 指的是外键名、实体字段名,其实都不是很准确,容易混淆,还是要动手做一下。

了解了JoinColumn 不妨进一步了解下 @JoinTable 的 JoinColumn 属性,这个也是比较容易混淆的。

三、@JoinTable 的 JoinColumn 属性

@JoinTable 一般和 @ManyToMany 使用,处理多对多关系,需要两个 Entity 有中间关系表。“一对多”一般不会使用关系表,而选择将“一”直接作为“多”的一个属性。这也是我们学数据库时听老师讲的常用方法。

JoinTable 有很多属性,但我们了解基本的 JoinColumn 相关属性即可,和我们上面说的一样,JoinColumn 实际上指的是数据库的字段,下面从 《Spring Data JPA 从入门到精通》截取的示例:
在这里插入图片描述
看起来好长,但实际上只用到 @JoinTable 只有三个属性:

  • name:数据库里的中间关系表名(blog_tag_relation)
  • joinColumns:当前表在关系表的链接字段(blog_id),一般我们会用 id
  • inverseJoinColumn:另一张表在关系表的链接字段(tag_id),一般我们会用 id

注意到我们使用 @JoinColumn 指定中间表的列,一定记住它使用的是数据库字段。对应的表结构如下:

Blog 表属性语义
idID
其他属性
Tag 表属性语义
idID
其他属性
blog_tag_relation 表属性语义
blog_idBlog 的 ID
tag_idTag 的 ID

全文结束。如果阅读了本文后你对如何区分和使用JPA属性有了更多的认识,请为我点个赞,让更多人关注我,这是我不断发文分享重要动力。

有问题欢迎留言讨论。

  • 20
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
如果你只想删除间表而不删除集合的实体类,可以使用JPA的@ManyToMany注解的cascade属性来实现。将cascade属性设置为CascadeType.REMOVE,表示在删除一个Role实体时,只删除Role与Permission之间的关系,而不删除Permission实体本身。 修改Role类的@ManyToMany注解,如下所示: ``` @ManyToMany(cascade = CascadeType.REMOVE) @JoinTable(name="system_role_permission", joinColumns=@JoinColumn(name="role_id", referencedColumnName="id"), inverseJoinColumns=@JoinColumn(name="permission_id", referencedColumnName="id") ) private List<Permission> permissions; ``` 这样,在删除Role实体时,只会删除Role与Permission之间的关系,而不会删除Permission实体本身。同理,如果你想删除Permission实体时,只删除Permission与Role之间的关系而不删除Role实体本身,可以在Permission类的@ManyToMany注解设置cascade属性为CascadeType.REMOVE。 完整代码如下所示: Role类: ``` @Entity public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToMany(cascade = CascadeType.REMOVE) @JoinTable(name="system_role_permission", joinColumns=@JoinColumn(name="role_id", referencedColumnName="id"), inverseJoinColumns=@JoinColumn(name="permission_id", referencedColumnName="id") ) private List<Permission> permissions; // getters and setters } ``` Permission类: ``` @Entity public class Permission { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToMany(mappedBy = "permissions", cascade = CascadeType.REMOVE) @JsonIgnore private List<Role> roles; // getters and setters } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值