關於@DynamicUpdate的誤解

先看證據


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

翻譯成白話文:

  • 對於更新,此實體是否應在使用動態sql生成時,僅在預處理sql語句中引用已更改的列。
  • 請注意,對於從新附加分離的實體,若是未啓用select-before-update,則沒法執行此操做。

舉栗子


先說明一下@DynamicUpdate註解用在實體類上java

有數據庫表tbl_foo和對應的實體類Foo,以下:web

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屬性,代碼以下:sql

Foo foo = fooDao.findById(1);
foo.setName("貝多芬");
fooDao.save(foo);
複製代碼

兩種狀況:數據庫

  1. 在entity類中未使用@DynamicUpdate註解或使用了@DynamicUpdate(false),那麼Hibernate底層執行的sql如:
update tbl_foo set name=?, col3=?, col4=?, col5=? where id=?
複製代碼
  1. 在entity類中使用了@DynamicUpdate註解(或@DynamicUpdate(true)),Hibernate底層執行的sql如:
update tbl_foo set name=? where id=?
複製代碼

以上兩種狀況對數據庫更新的結果是等效的,可是使用@DynamicUpdate性能會好一些。由於不使用@DynamicUpdate時,即便沒有改變的字段也會被更新。若是進行頻繁的更新操做,而且每次只更新少數字段,那麼@DynamicUpdate對性能的優化效果仍是很好的。api

誤解


咱們常有一種需求,web層用對象接收前端要修改的屬性值(不修改的值爲空),咱們但願直接調用dao的update方法進行選擇更新。性能

web層使用對象接收前端要修改的屬性值,可等效看作執行以下代碼:學習

Foo foo = new Foo();
foo.setId(1);
foo.setName("貝多芬");
複製代碼

這時服務層直接使用這個對象進行更新優化

fooDao.update(foo);
複製代碼

咱們期待的結果:spa

id name col3 col4 col5
1 貝多芬 1770 奧地利

看到網上有些文章說在實體類加上@DynamicUpdate,就能夠知足咱們的以上需求,可是很遺憾,否則!

反而獲得這樣的結果是:

id name col3 col4 col5
1 貝多芬

只要徹底理解了api-doc中對@DynamicUpdat的說明,就很容易知道獲得這個結果的緣由了。@DynamicUpdate的動態更新的含義是,比較更新要使用的實體類中的字段值與從數據庫中查詢出來的字段值,判斷其是否有修改。看這個例子,數據庫中id=1的記錄全部字段都是非空的,可是實體類中只有name有值,也就是全部字段都變了,只是其餘字段被更新爲了新的空值。

閒言碎語(一些廢話能夠忽略)


  • 學習一個註解(或者類)的用法,無論是開源的仍是商業的,最簡單、最靠譜、最直接的途徑就是一手的官方api文檔。

  • 有些小哥哥在使用Spring Data JPA時用到了@DynamicUpdate,就理算固然的認爲它和Spring是一家,其實否則。其實從引用註解時的包名就能看出來,很明顯Hibernate纔是它的原配。緣由固然就是Spring Data JPA使用的ORM實現是Hibernate。因此也就解釋了上圖中的文檔是Hibernate的api文檔,而不是Spring或者Java的api文檔。

以上所有爲我的觀點,但願對你有幫助。本人水平有限,不免有不妥或者謬誤之處,望你們指出。有其餘問題也歡迎和你們交流!

相關文章
相關標籤/搜索