目錄
- 現象
- 產生的原因
- 解決方法
現象
最近解決了一個困惑幾天的bug,資料庫里的某一些記錄莫名其妙的被重繪了,排查過代碼跟應用日志,可以確定不是代碼執行的更新,直到今天看到了一條日志,在事務提交時報錯“Column 'user_name' cannot be null”,在出錯的事務中,針對這一個表只會執行query不會執行update,而這個報錯資訊是只有insert或者update時才有可能出現,這就意味著事務中自動在這個表執行了的insert或者update陳述句,
產生的原因
JPA通過EntityManager對資料庫物體類進行管理,而物體物件的狀態有new/managed/removed/detached四種狀態,如下圖所示

-
瞬時狀態(new/transient):
當一個物體物件最初被創建時,它的狀態是New或Transient,在這種狀態下,物件還沒有與EntityManager關聯,并且不存在資料庫中, -
持久/托管狀態(managed):
當物體物件通過EntityManager的persist()方法持久化到資料庫時,它就變成了Managed或Persistent,如果我們更改持久狀態物件的值,則在提交事務時自動與資料庫同步,由EntityManager從資料庫檢索的物體物件也處于Managed狀態, -
游離狀態(detached):
狀態Detached表示已經與EntityManager斷開連接的物體物件,物件識別符號應該在資料庫表中,物件不與持久化背景關系相關聯,當關閉hibernate會話時,實體將失去與持久性管理器的關聯,我們把這些物體稱為分離的,表明它們的狀態不再保證與資料庫同步,游離的物件可以在以后的時間點重新附加到新會話,使其以及所有修改再次持久化 -
移除狀態(removed):
通過在活動事務中使用entitymanager的remove(),也可以將持久狀態物體物件標記為要洗掉,然后,物體物件將其狀態從Managed更改為Removed,并在提交期間從資料庫中物理洗掉,
當資料從資料庫查出來時,該資料物件處于managed狀態中,管理物體物件在活動事務中被修改,該更改由所屬的EntityManager檢測到,并在事務提交時將更新到資料庫
一旦物體物件從資料庫中檢索出來,它可以在記憶體中修改將會反映到資料庫當中,如下偽代碼
EntityManager em;
Employee employee = em.find(Employee.class, 1);
em.getTransaction().begin();
employee.setNickname("Ram");
em.getTransaction().commit();
當事務提交時,物體物件在資料庫中nickName將會更新為Ram,而代碼中并沒有呼叫persist(),
解決方法
避免直接修改處于managed狀態的資料物件,可以復制物件,使用副本
本文來自博客園,作者:IAyue,轉載請注明原文鏈接:https://www.cnblogs.com/zmj-pr/p/16033530.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/555668.html
標籤:其他
上一篇:【numpy基礎】--基礎操作
下一篇:返回列表
