Spring JPA 实体类 save 方法都执行了那些语句?

本文详细解析了Spring JPA中save方法在单个实体类、ManyToOne关系及ManyToMany关系中的执行逻辑,包括何时执行insert和update语句,以及在多对多关系中如何处理关联表的操作。总结了不同情况下save方法对主键和外键的检查及数据库操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

insert 或 update 都是通过调用 JpaRepository 的 save 方法实现的。

本文以 User,Role,Group (用户,角色,组)为例进行阐述。

用户和角色是多对多关系,用户和组是多对一关系。

单个实体类的 save

对于实体类 User ,调用 save(user) 方法,分为以下情况讨论:

  • 假如 user 的主键字段(@Id 修饰的字段)为空,是新增方法,执行一条 insert 语句。

  • 假如主键字段不为空则会先执行 select 语句,查看当前主键对应的 user 是否存在。
    - 假如不存在则执行 insert 语句,需要注意的是如果主键有自动生成规则,保存的主键则会根据数据库的规则生成而不是设置的值。
    - 假如存在则比较字段值有无变化,有变化则执行 update 语句。

总结如下:

  • 执行 insert 语句的条件:待保存的实体类主键为空,或者主键是一个在数据库中不存在的值。
  • 执行 update 语句的条件:待保存的实体类主键不为空并且主键是一个在数据库中存在的值,并且相比数据库存在的值有变化。

ManyToOne 关系中的 save

对于实体类 User 和 Group,User 与 Group 的关系是多对一关系,Group 与 User 的关系是一对多关系。
多对一关系中,一般不会新建关系表,User 实体类中有一个字段是 Group 类型

@ManyToOne
@JoinColumn(name = "group_id")
private Group group;

相应的 User 表中有一个 group_id 字段关联 Group 表。

对于实体类 User ,调用 save(user) 方法,假如 user 内部的 group 不为空并且 group 没有设置主键字段,则会报错。假如 user 内部的 group 不为空并且 group 设置了主键并且主键在表中不存在,则会报错。报错都是因为数据库硬性指定了外键。

只有 group 为空,或者 group 不为空并且主键字段对应的数据在 Group 表中存在的时候才不会报错。

ManyToMany 关系中的 save

假设 User 和 Role 两个实体是多对多关系。通过 @ManyToMany 注释,JPA 会自动生成并维护 user 和 role 的关系表。

user 里面有个集合是 roles,标注了多对多关系。

@ManyToMany
@JoinTable(name = "user_role",
            joinColumns = {@JoinColumn(name = "user_id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id")})
private List<Role> roles;

调用 save(user) 方法时,roles 字段的要求如下:

  • roles 集合可以为空,若为空调用 save(user) 方法:假如 user 执行的是 update 语句,则会删除所有当前 user 主键字段的关系。假如 user 执行的是 insert 语句,则对关系表没有操作。

  • roles 若不为空调用 save(user) 方法:假如 user 执行的是 update 语句,则会删除所有当前 user 主键字段的关系,然后重新插入(例外情况就是从数据库中查询出 user 后,对此 user 的 roles 元素没有增删或者更改主键字段,更改元素的其它字段没关系,此时对关系表不会有任何操作)。假如 user 执行的是 insert 语句,则对关系表直接插入。无论 insert 还是 update,集合中所有元素的主键字段不能为空或者不存在的值,否则会报错。

需要注意的是,上面对 role 的主键必须存在的情形,只有在 @ManyToMany 的 cascade 字段没有开启级联关联的时候才符合,假如开启插入关联,则会自动在 role 表中插入数据,需另外讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值