我正在考慮Hibernate管理的類層次結構的表佈局,當然每個子類的表技術在一般意義上都是最合適的。但是,通過邏輯思考,我對它的性能有一些擔憂,特別是隨着子類數量的增加。Hibernate的每個子類的繼承策略的效率
舉一個非常簡短的(和經典)例如,假設您有以下類:
public abstract class Animal {
int pkey;
String name;
}
public class Dog extends Animal {
long numSlippersChewed; // int is not large enough...
}
public class Cat extends Animal {
short miceCaught; // ... but here int is far bigger than required :-)
}
(我eliding getter和setter和Hibernate映射等等,僅僅假設他們是基本明顯的情況)。
這些實體的數據庫表是有意義的,你會得到很好的非規範化等等。但是,Hibernate爲了取出個體動物而做了什麼查詢呢?我能想到的至少兩種情況下,這可能會發生:
- 有一個對一個(或一個一對多)映射,如
Human
類的pet
領域的一些其他實體。這將存儲pkey,所以當Hibernate獲取一個Human對象時,它也需要獲取相應的Animal
對象。當給定動物的pkey時,Hibernate會使用什麼查詢來提取和解組實際動物數據,因爲它可能位於Cat
或Dog
表中? - HQL如
from Animal where name='Rex'
(讓我們假設名稱是唯一的)。這與上述類似,因爲它可以讓您在超類表中標識一行,但您不知道要檢查哪個子類表以獲取更多詳細信息。 HQL是否甚至允許您發出查詢from
抽象類? (儘管使用子類特定的東西很好,例如from Cat where miceCaught > 5
)。
我可以想到兩種方式,這可以在SQL中完成,而且看起來都不漂亮。一種是針對給定的pkey在每個子類表上運行exists
查詢,然後從返回命中的表中加載。或者,Hibernate可以在所有表中執行一些可怕的聯合查詢 - 實質上是模擬每個層次表的方案,因爲結果集將包含所有可能子類的屬性,並且子類表中的各個選擇返回null
作爲無關參數。後一種情況可能甚至需要添加一個合成鑑別器列,以便Hibernate可以知道哪個子類表實際返回了該行,從而知道應該分析哪些Java類。
事情變得多毛太多,如果你有具體的類型的亞型:
public class Greyhound extends Dog {
float lifetimeRacingWinnings;
}
現在對於一個給定的動物p鍵,有可能是在Dog
和Greyhound
表有效行,這意味着我的第一種手動檢查與pkey相對應的類的方法變得更加困難。
我非常擔心的原因是我會希望在類層次結構上使用這種方法,最多有70個類,最大嵌套鏈的級別爲4-5,因此對所有這些進行聯合查詢是可能會有可怕的表現。 Hibernate有沒有什麼小竅門可以保持這種相對高性能?或者正在通過pkey加載對這些類中的一個的引用需要很長時間?
也許你想看到http://stackoverflow.com/questions/2700680/table-per-subclass-inheritance-relationship-how-to-query-against-the-parent-clas – 2010-06-18 01:49:40
出於好奇我不知道是否其他一些基於JPA對象的存儲系統也有同樣的問題(即ObjectDB)。換句話說,也許標準的關係數據庫可能不是最好的技術,特別是因爲你有一個巨大的對象圖。 – 2010-12-25 15:36:38