hibernate高階改造

2021-08-31 18:00:01 字數 2292 閱讀 3986

原帖內容已刪除,對描述部分做新的修改,將不針對hibernate這乙個orm框架:

我將會致力於從根本上解決髒資料讀取問題。

對於我們現在的大多數框架來說,任何操作都是基於資料庫的。相當於把sql語言轉換形式進行實現:

"update user set level = level +1;" 

等價於"user user= get(user); user.setlevel(user.getlevel+1);"?

我們的應用都是基於資料庫的資料操作,前者是告訴資料庫自行修改資料操作,而後者著是直接替換資料庫中的值!

有嚴重的併發修改問題。所謂併發修改不僅僅是同一時間修改同一條記錄的時候的問題,這種情況資料庫有鎖等方式解決。

但是對於後者這種方式,資料庫將無能為力,因為orm框架每次update到資料庫中的值全部都是全新的!全部都是替換操作。

在併發修改的情況下(從 user user= get(user);把user資訊取出來到update(user);這個過程中,任何乙個其他執行緒的 get(user) update(user) ;操作都會照成潛在的併發問題。第乙個取出的user的物件是可靠的,其他的非指向user引用的物件全部都為不可靠資料!)user的資訊會被任意的覆蓋,因為所有的user資訊都是取得儲存在記憶體中,資料庫中uid為1的user記錄在資料庫中永遠只有乙個,並且有鎖機制保證修改順序。

但是在orm框架中會存在多個user物件,只不過這些user物件的uid為1,而且可怕的是這些user互不相關!在你update(user);的時候實質上是在不停的插入全新的user資訊,記憶體中的user值和資料庫中的值沒有任何關係。但是,從業務邏輯上來說,你對user物件屬性操作僅僅是代替資料庫操作。

本質上user的屬性在整個記憶體

中應當只有1個,因為你只是代替資料庫去修改某個屬性。你不應該具有多個儲存能力,每個實體實質上都儲存了一條記錄的資訊。

舉例:

@transactional

public void a()

在這個方法裡面,任意對user的操作都是可靠的,因為hibernate的一級快取將後面取出來的user2指向的是user1的引用,user1、user2的修改實質上僅僅修改記憶體中的唯一user物件。在update之後沒有任何問題,因為從始至終只修改的是乙個記錄。

典型的併發修改例子:

@transactional

public void b()

@transactional

public void c() catch (interruptedexception e)

basedao.update(user3);

}

b方法比c方法晚一秒鐘呼叫,假設user的leve原本的值為1;在method b,method c執行完畢之後 資料庫中實際值為2,而不是3。

因為b方法修改的資料庫記錄被c方法的修改結果覆蓋了。

這類問題根本原因不是用加鎖或者修改業務邏輯去解決的。而是為什麼在記憶體中會有多個不一樣的user。資料應該都是唯一的,資料庫中找不到id為1的2條記錄,記憶體中也不應該出現id為1的2個物件。

既然我們是orm框架用物件導向的方式去修改資料,運算元據的本質應該不能改變:既永遠只操作一條記錄。可以參照method a是如何實現的,無論你update(user);多少次,最終修改的只有一條記錄。只不過hibernate這種方式僅僅在乙個事物中是這樣做的,沒有做到整個記憶體中只存在乙個user物件。

針對,hibernate這個orm框架來說。他可以用一級快取保證同乙個事物內資料的一致性,但是處理不了不同事物的一致。那麼還有乙個二級快取可能讓記憶體中的user指向同乙個物件(應該是有的),具體有沒有這麼做,還需要測試、研究下才能最終確認。

如果我的推斷是正確的,那麼在hibernate開啟二級快取之後,才能算是乙個完整的orm框架。否則將是乙個錯誤設計,簡單的說:資料中只有一條記錄,那麼記憶體中只能有乙個實體,update操作只能由這個實體操作,其他的任意實體都不可取。你以為你按照產品說明書上一步步操作沒有問題,實際上問題一直存在!只不過你沒有碰。

ps:1、我是在接觸遊戲開發才有這個想法,至於一些設計可能你覺得有問題,這個不想多爭論,除非你指出我設計上的錯誤。

2、併發問題、併發壓力之類的,一般都說的是資料庫底層操作的問題,但是實際在業務方法上你可能悄無聲息的製造了併發問題。

3、這裡請不要說xx不適合開發xx之類的,這裡說的和開發什麼東西沒太大關係,任何乙個使用hibernate的應用都會有這樣的問題,除非你從業務上就避免了多個地方修改同一條記錄的邏輯。一旦有,你就應該有這個思考。

4、如果錯,請狂噴。在下洗耳恭聽、虛心學習。

Hibernate高階工具類詳解

在進行entitymanager與transaction物件之前我們應該先對工廠物件進行封裝 下面這段 中封裝了我們的核心業務 其實可以簡單理解為對物件的操作,result executor.execute entitymanager 在未進行工具類封裝前提先我們業務實現需要依靠如下 業務 將在jp...

hibernate高階 多對多對映

前面學習了一對多對映,對hibernate的配置有一定大了解,在實際開發中還有一種對映關係就是多對多對映,比如乙個公司中開發人員和專案之間就是多對多的關係,乙個開發人員可以同時參與幾個專案,當然乙個專案可以有多個人員參與。首先就是在資料庫中建立三張表,除了本來的雇員表和專案表外,另外一張表來儲存兩者...

ORM高階 Hibernate的優劣對照

hibernate 是一種是輕量級的 框架。學過 entityframework 的。會感覺挺親切的。對於各種層次程式猿對資料庫的設計 小菜程式設計師這樣做 首先考慮資料的儲存,對於功能的實現,怎樣方便怎樣來。至於說冗餘神馬的。不予考慮。資深程式設計師這樣做 首先設計資料庫的關係模型。用工具畫畫 e...