JPA记事本

源:https://blog.ximinghui.org/3b14f3d1/index.html

Cascade

JPA的关系注解,ManyToMany、OneToOne、ManyToOne等,都有一个cascade属性,指向一组CascadeType枚举值。

public enum CascadeType { 
    ALL, PERSIST, MERGE, REMOVE,REFRESH,DETACH
}

这些值将决定当前操作实体中的另一个实体引用字段,与实际持久化数据不一致时,是否级联更新。

默认等效于空,即 @ManyToMany(cascade = {})。ALL表示包含所有。具体枚举用处和使用场景去网上查阅,这里不再解释。

JPA实体的生命周期

JPA 实体的生命周期分为四种状态:新建(New/Transient)、托管(Managed)、脱管(Detached)和删除(Removed)。

状态转换图:

新建 ─────persist()────→ 托管 ───remove()───→ 删除
            ↑                  ↑↓
            │                  │
            └──────merge()─────┘
                   detach()

CascadeType需要注意的点

默认情况下cascade为空,所以不会执行任何关联更新。这种情况下,更新实体时不会关联更新引用实体的信息,即只更新当前实体和实体间的关系(对应数据库中关系表)。常见的场景,如通过HTTP接口接收JSON数据或Spring Data仓库数据初始化,若有如下格式:

[
  {
    "_class": "org.ximinghui.study.User",
    "userId": "8f3e",
    "username": "ximinghui",
    "password": "123456",
    "firstName": "Xi",
    "lastName": "Minghui",
    "sex": "MALE",
    "birthday": "1998-01-01",
    "lastLoginTime": "2024-11-04T23:27:31+00:00",
    "userGroups": [],
    "permissionSets": [
      {
        "number": 1,
        "_remark": "只能在这里添加主键进行关系维护,并不能通过添加权限集的其它属性来实现更新权限集目的",
        "name": "New Name",
        "permissions": ["ALL_PERMISSIONS"]
      }
    ],
    "isEnabled": true
  }
]

即使数据中指定了PermissionSet对象的name和permissions属性,JPA也不会更新PermissionSet实体,它只会维护该User实体和number为1的PermissionSet实体间的关系。

但是,如果设置了CascadeType包含级联更新后,如下:

// ...
public class User{
    // ...

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) // 
    private Set<PermissionSet> permissionSets = new LinkedHashSet<>();

    // ...
}

这会导致上面的示范JSON数据级联更新PermissionSet实体,因此在设计cascade请考虑到可能存在的安全隐患和意外的实体更新情况!!!


ximinghui
1 声望0 粉丝

一枚普普通通的程序猿