示例場景
我有一個控制列總值的限制。如果我進行了超過此限制的保存,我希望它拋出例外。例如;
假設我已經添加了以下資料:LIMIT = 20
| ID | 代碼 | 價值 |
|---|---|---|
| 1 | 一個 | 15 |
| 2 | 一個 | 5 |
| 3 | 乙 | 12 |
| 4 | 乙 | 3 |
- 如果我插入 (A,2) 它超過限制,我想得到例外
- 如果我插入 (B,4) 交易應該成功,因為它沒有超過限制
- 代碼和值是相互關聯的
我能做什么
我可以使用所需的查詢來檢查此場景。例如,我為它撰寫了一個方法,我可以在保存方法中檢查它。而已。
但是,我正在尋找比這更有用的解決方案
- 比如設計Entity的時候有沒有注解?
- 我可以在不每次都呼叫提供此控制元件的方法的情況下執行此操作嗎?
我可以舉什么例子?
@UniqueConstraint檢查它是否添加了相同的值
uj5u.com熱心網友回復:
Hibernate 和 Spring Data JPA 都沒有為此場景內置任何內容。您必須自己在存盤庫中撰寫事務邏輯:
@PersistenceContext
EntityManager em;
public addValue(String code, int value) {
var checkQuery = em.createQuery("SELECT SUM(value) FROM Entity WHERE code = :code", Integer.class);
checkQuery.setParameter("code", code);
if (checkQuery.getSingleResult() value > 20) {
throw new LimitExceededException("attempted to exceed limit for " code);
}
var newEntity = new Entity();
newEntity.setCode(code);
newEntity.setValue(value);
em.persist(newEntity);
}
然后(這很重要!)您必須SERIALIZABLE在@Transactional注釋上為使用該表的方法定義隔離級別。
在此處閱讀有關可序列化隔離級別的更多資訊,它們有一個奇怪的相似示例。
請注意,您必須考慮重試失敗的事務。不知道如何用 Spring 做到這一點。
uj5u.com熱心網友回復:
使用事務
最常見和長期被接受的方法是以合適的形式(在類、庫、服務等中)簡單地抽象出在事務中控制您所描述的行為的業務規則:
@Transactional(propagation = Propagation.REQUIRED)
public RetType operation(ReqType args) {
...
perform operations;
...
if(fail post conditions)
throw ...;
...
}
在這種情況下,如果在呼叫方法時已經有一個打開的事務,則該事務將被使用(并且不會有互鎖),如果沒有創建事務,它將創建一個新的,以便操作和后置條件檢查在同一事務中執行。
請注意,使用此策略,操作和不變檢查事務都可以組合由TransactionManager管理的多個事務狀態(例如,Redis、MySQL、MQS...同時并以協調的方式)。
僅使用資料庫
很長時間沒有使用它(支持第一種方式),但使用 TRIGGERS 是幾十年前用于檢查后置條件的規范選項,但此解決方案通常與特定的資料庫引擎耦合(例如在PostgreSQL或MySQL 中) .
在進行修改的客戶端無法或不愿意(不安全)檢查事務中的后置條件(例如 bash 行程)的情況下,它可能很有用。但是現在已經很少見了。
在某些需要效率的場景中,使用 TRIGGERS 也可能更可取,因為資料庫腳本中有某些優化選項。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/385775.html
