2011-04-14 68 views
5

我使用Hibernate 3.2.2 GA與HSQLDB 2.0 GA,和我有類似下面這樣的類層次結構:休眠:org.hibernate.WrongClassException,SINGLE_TABLE繼承和DiscriminatorFormula

@Entity 
@Table(name = "A_TABLE") 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@DiscriminatorFormula(value = "case when CODE IN (1, 2, 3, 4) then 'TypeB' 
when CODE IN (5, 6, 7, 8) then 'TypeC' else NULL end") 
@org.hibernate.annotations.Entity(dynamicUpdate = true, dynamicInsert = true) 
public abstract class A{ 

(...) 

} 


@Entity 
@DiscriminatorValue("TypeB") 
public class B extends A { 

(...) 

} 


@Entity 
@DiscriminatorValue("TypeC") 
public class C extends A { 

(...) 

} 

我試圖執行下面的HQL查詢,它返回來自B和C類的對象。

String hql = "from A a where a.someAttr = 3"; 
Query query = session.createQuery(hql); 

return query.list(); 

不過,我得到以下錯誤:

org.hibernate.WrongClassException: Object with id: 2 was not of the specified subclass: A (Discriminator: C  ) 

最奇怪的是,ID爲2 對象是一個C實例...

我GOOGLE了這個錯誤,我發現一些人面對它,但沒有使用InheritanceType.SINGLE_TABLEDiscrimatorFormula。有沒有人遇到這個問題?

+0

我已經通過了這個。如果可以,請將調試器附加到Hibernate'Loader'或'SingleTableEntityPersister'類。後者將實際的子類存儲在字段'subclassesByDiscriminatorValue'中。檢查鑰匙,並比較那裏實際傳遞的內容。你的輸入看起來可疑地用空白填充。 – mabi 2013-03-27 14:56:23

回答

0

問題是,你正在得到A的列表,而Hibernate並不知道足以根據鑑別器公式在列表中創建B或C。幸運的是,有一個註解來解決這個問題。

有人把這稱爲一個錯誤,而且我傾向於同意。無論如何,抽象似乎有點漏洞。

添加@ForceDiscriminator註釋到母公司(A),它很可能正常工作。

該解決方案是Hibernate特有的。我不確定問題是否延伸到JPA,或者是否有JPA解決方案。

編輯:

這似乎沒有做的伎倆。

嘗試獲取休眠狀態爲您生成的SQL可能是值得的。

添加

<property name="hibernate.show.sql" value="true" /> 

你休眠的配置,看看會發生什麼。

使用和不使用force子句獲取這個sql可能會提供有關這個force究竟是什麼以及它爲什麼不起作用的線索。

現在除了NULL在您的鑑別器公式中看起來有點冒險之外,我現在還無法想到其他任何東西。

+1

它沒有工作。在將@ForceDiscriminator添加到A後,我仍然收到WrongClassException。還有其他想法嗎?謝謝! – Porcho 2011-04-15 17:02:11

1

好了,這讓我好奇:它可能是你從this issue遭受它說:

The reason is the string is interpreted as a CHAR type rather than VARCHAR. We may change this behaviour in the future.

你可以嘗試的結果(內@DiscriminatorFormula)或測試與其他DBMS應用TRIM()?這似乎並不是Hibernate特有的。

1

我使用DTYPE列和WHERE子句解決了它。 以你爲例,它應該是:

@Entity 
@WHERE(clause = "DTYPE = 'B'") 
public class B extends A { 
... 
} 


@Entity 
@WHERE(clause = "DTYPE = 'C'") 
public class C extends A { 
... 
}