hibernate關於事務和sqlsession的幾個坑
我們知道hibernate是ORM關係型資料庫。和資料庫互動的時候需要sqlsession,如果是儲存、更新、刪除操作的時候,還需要有事務。
在spring和hibernate整合的時候,事務都是有spring來處理。有的時候會遇到坑。
異常一:
Could not obtain transaction-synchronized Session for current thread
之前沒有問題的。因為修改了部分程式碼後出現了這個問題。
經過對比之後,發現正當時情況下:
在service層使用了類級別的事務。使用的是spring的@Transactional註解。
出現異常的時候,是事務註解被註釋掉了。
錯誤程式碼:
使用的是:Session session = getCurrentSession();這個方法。
經過查詢得到:
hibernate的sessionFactory中getCurrentSession()方法和OpenSession方法的區別:
所以,Could not obtain transaction-synchronized Session for current thread這個異常的原因是因為使用了 getCurrentSession();獲取session 而沒有使用@Transactional導致的。
擴充套件:
使用@Transactional預設只有當方法中丟擲unchecked的runtimeException時,才會進行回滾,丟擲需捕獲的Exception異常是不能進行回滾的
異常二:
A different object with the same identifier value was already associated with the session
錯誤截圖:
錯誤再現:
先查詢。如果存在,重新set指定欄位值之後,呼叫saveOrUpdateEntity的方法。就出現這個異常。
根據錯誤提示,可以分析得到:
在同一個session中,存在兩個相同的標識(如主鍵id),但是這兩個實體有不是相同的。
雖然使用了:
BaseNewinfoViewTotal entity =model.map(bean,BaseNewinfoViewTotal.class);
其實質也相當於是new了一個BaseNewinfoViewTotal 物件。然後重新賦值而已。
所以,兩個物件都有相同的主鍵ID,但是在記憶體中是兩個不同的物件。
這個時候解決方案:
採用session.merge (object c)代替session.save(object c),即可解決
歡迎關注凱哥公眾號:凱哥Java