關於@DynamicUpdate的誤解
二話不說,先把@DynamicUpdate的官方api-doc呈出來(如下圖),參見https://docs.jboss.org/hibernate/stable/orm/javadocs/

翻譯成白話文:
- 對於更新,此實體是否應在使用動態sql生成時,僅在預處理sql語句中引用已更改的列。
- 請注意,對於重新附加分離的實體,如果未啟用select-before-update,則無法執行此操作。
舉栗子
先說明一下@DynamicUpdate註解用在實體類上
有資料庫表tbl_foo和對應的實體類Foo,如下:
id | name | col3 | col4 | col5 |
---|---|---|---|---|
1 | 畢加索 | 1770 | 奧地利 | 男 |
class Foo{ private Integer id; private String name; private String col3; private String col4; private String col5; getter... setter... } 複製程式碼
在Service中更新id=1記錄的name屬性,程式碼如下:
Foo foo = fooDao.findById(1); foo.setName("貝多芬"); fooDao.save(foo); 複製程式碼
兩種情況:
- 在entity類中未使用@DynamicUpdate註解或使用了@DynamicUpdate(false),那麼Hibernate底層執行的sql如:
update tbl_foo set name=?, col3=?, col4=?, col5=? where id=? 複製程式碼
- 在entity類中使用了@DynamicUpdate註解(或@DynamicUpdate(true)),Hibernate底層執行的sql如:
update tbl_foo set name=? where id=? 複製程式碼
以上兩種情況對資料庫更新的結果是等效的,但是使用@DynamicUpdate效能會好一些。因為不使用@DynamicUpdate時,即使沒有改變的欄位也會被更新。如果進行頻繁的更新操作,並且每次只更新少數字段,那麼@DynamicUpdate對效能的優化效果還是很好的。
誤解
我們常有一種需求,web層用物件接收前端要修改的屬性值(不修改的值為空),我們希望直接呼叫dao的update方法進行選擇更新。
web層使用物件接收前端要修改的屬性值,可等效看做執行如下程式碼:
Foo foo = new Foo(); foo.setId(1); foo.setName("貝多芬"); 複製程式碼
這時服務層直接使用這個物件進行更新
fooDao.update(foo); 複製程式碼
我們期待的結果:
id | name | col3 | col4 | col5 |
---|---|---|---|---|
1 | 貝多芬 | 1770 | 奧地利 | 男 |
看到網上有些文章說在實體類加上@DynamicUpdate,就可以滿足我們的以上需求,但是很遺憾,不然!
反而得到這樣的結果是:
id | name | col3 | col4 | col5 |
---|---|---|---|---|
1 | 貝多芬 |
只要完全理解了api-doc中對@DynamicUpdat的說明,就很容易知道得到這個結果的原因了。@DynamicUpdate的動態更新的含義是,比較更新要使用的實體類中的欄位值與從資料庫中查詢出來的欄位值,判斷其是否有修改。看這個例子,資料庫中id=1的記錄所有欄位都是非空的,但是實體類中只有name有值,也就是所有欄位都變了,只是其他欄位被更新為了新的空值。