博客 / 詳情

返回

JPA記事本

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請考慮到可能存在的安全隱患和意外的實體更新情況!!!

user avatar eisuto 頭像 cunyu1943 頭像
2 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.