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