項目中遇到的問題以及解決方案(Java後臺)

有經驗可以少走點彎路,所以走過的坑要記住,雖然我們不能兩次踏入同一條河流,但我們可能多次掉入同一個坑!
1、最近項目做一個關於批量修改或者增加記錄的功能,爲了方便,就手動寫一個saveOrUpdate()函數,你可能會說這個hibernate不是自帶嗎?我首先說一下項目的情況:
從前臺傳來的多條記錄,是沒有主鍵的,(因爲主鍵自動增長,且前臺可以新增或修改多條數據,所以編輯前查詢也有沒有顯示自動增長主鍵,當然這也有一個解決方案:編輯之前查詢數據結果顯示在前臺包含自動增長主鍵,新增數據記錄就不包含主鍵,這樣後臺根據有沒有主鍵來操作是save還是update,不想改所以今天不是這種情況)
所以今天的目的就是自己寫一個saveOrUpdate()函數,可以處理save或者update,本來想的流程是:
1)、從前臺獲取對象,然後根據一個條件(其實這個條件也可以是主鍵且保證唯一)查詢數據庫是否有這條記錄;
2)、如果沒有則用hibernate自帶save()函數完成插入操作,否則把前臺對象A的主鍵設置爲從數據庫獲得的A1,然後使用hibernate自帶函數Update()進行更新,想到這裏我覺得一且很順利,But。
3)、實際操作起來,並不是這樣的,save()沒什麼問題,畢竟數據庫沒有,session緩存也沒有;但是Update就會報錯:org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:[com.fatkun.dao.hibernate.User#12]
反正就是說,當前session對象(我用的是getCurrentSession(),而不是create..),session緩存裏面已經有一個主鍵一樣的對象(標識),系統認爲是同一個(我這裏猜測應該是根據主鍵來判斷是否是同一個對象),所以用當前session查詢出A1,然後設置前臺傳來對象A,然後Update(A),就會報錯的,當前session緩存裏就有A1,這個時候換成A,就會衝突了。
囉嗦了這麼多,來說解決方案:
《1》使用Hibernate自帶的merge()函數,如果前臺對象包含主鍵,直接使用,比saveOrUpdate更好用。
《2》可以把session緩存對象去掉 ,然後使用hibernate自帶update():

        @Override
    public void forceUpdate(T o,T oo) {
        // 這裏必須兩個對象,試圖用一個用臨時變量保存然後脫管再update不行
        //我這裏o是session緩存中已經包含的,需要脫管,然後用oo來更新數據庫。
        if(this.getCurrentSession().contains(o)){
            this.getCurrentSession().evict(o);
            this.getCurrentSession().update(oo);
        }else{
            this.getCurrentSession().update(o);
        }

    }
《3》 用另一種方法,就是把對象A的屬性值覆蓋A1(可以主鍵不覆蓋),然後update(A1).
BeanUtils.copyProperties(A1,A); 即將A的值賦值給A1。
《4》最簡單方便的方式就是查詢結果傳給前臺包含自動增長主鍵,這樣新增的就主鍵爲空,用save(),修改的包含主鍵,則直接update(),不查詢,因爲編輯是默認有主鍵的,有主鍵代表默認數據庫有記錄,不用查,當然適合不刪除數據的部分。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章