如何解決 hibernate 自動更新實體類的問題
示例:
GrabOrder grabOrder = (GrabOrder)this.grabOrderDao.getCurrentSession().get(GrabOrder.class,grabOrderId); grabOrder.setNickname(TimeHWUtil.getCurrentDateTime());
上述代碼 會執行兩條SQL:
查詢和更新
爲什麼會更新呢?我明明沒有調用DAO的update方法啊!!!
但是這裏我調用了實體類的setter方法,
hibernate有一個機制:Hibernate dirty-checks,會同步session緩存和數據庫的數據.
如何解決 自動更新的問題:
方案一:把實體類由持久態變爲脫管態(遊離態)
this.grabOrderDao.getCurrentSession().evict(grabOrder);
缺點:懶加載的對象無法加載,因爲此時session相當於close了
而且會報錯:org.hibernate.LazyInitializationException: could not initialize proxy - no Session
報錯的代碼:
this.grabOrderDao.getCurrentSession().clear(); System.out.println(grabOrder.getHouseInfo().getHouseOwner().getId());
更好的操作步驟:
(1)先把要訪問的屬性加載出來,可以通過提前使用,或者Hibernate.initialize(dept)
(2)再調用evict方法或clear方法
什麼叫提前使用呢?即提前調用getter方法
正確:
System.out.println(grabOrder.getHouseInfo().getHouseOwner().getId()); this.grabOrderDao.getCurrentSession().clear(); System.out.println(grabOrder.getHouseInfo().getHouseOwner().getId());
方案二:把實體類變爲只讀
this.grabOrderDao.setReadOnly(grabOrder, readonly);
但是這招不是萬靈藥,有例外,看官網:
12.2.2.2. Unidirectional one-to-many and many-to-many
Hibernate treats unidirectional one-to-many and many-to-many associations owned by a read-only entity the same as when owned by an entity that is not read-only.
修改 單向的一對多和多對多的成員變量時,依然會觸發hibernate的自動更新.
有什麼萬全之策呢?
(a)採用讀寫分離,把操作放在只讀的數據庫連接中
(b)採用只讀事務
當方法名是updateTestLazy 時會自動更新
但是我修改方法名爲getTestLazy時,就不會自動更新了
爲什麼呢?看看spring 事務配置
只讀的對象 不保險,所以我們使用只讀的事務或只讀的數據庫連接.
如何解決 json序列化時,自動加載lazy對象導致對象多層嵌套的問題?
使用 SimpleBeanPropertyFilter過濾不需要的字段
/*** * * @param xpath : 參考 com/kunlunsoft/util/objectxpath/ObjectXpath.java * @return */ public String toJson(String column, String... xpath) { if (this.result == null) {//modified by huangweii @2015-08-17 System.out.println("this.result is null"); } else { if (this.result != false) { // this.errorMessage = null; this.setErrorMessage(null); } } if (ValueWidget.isNullOrEmpty(xpath) || ValueWidget.isNullOrEmpty(xpath[0])) { return HWJacksonUtils.getJsonP(this); } // final ObjectXpath oxp = new ObjectXpath(); int length = xpath.length; // final Object[] filterObjects = new Object[length]; List filterObjList = new ArrayList(); for (int i = 0; i < length; i++) { Object o = XPathParser.process(this.getValue(), xpath[i]); if (o instanceof List) { filterObjList.addAll((List) o); } else { filterObjList.add(o); } // filterObjects[i] = o; } final Object[] filterObjects = filterObjList.toArray(); return HWJacksonUtils.getJsonP(this, new DefaultJsonFilterDecide() { @Override public boolean isFilteColumn(Object pojo, Object propertyVal, String column2) { if (ValueWidget.isNullOrEmpty(column)) { if (SystemHWUtil.isEquals(propertyVal, filterObjects)) { return true; } } else { if (SystemHWUtil.isEquals(pojo, filterObjects) && (column2.equals(column))) { return true; } } return false; } }); }