2011-11-22 46 views
2

我的情況是這樣的:休眠個createCriteria在接口上使N次查詢,而不是1種

我們有一個超類,「MyAbstractEntity」

@Entity 
@Table(name = "MyTable") 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING) 
@DiscriminatorValue("FOO") 
public abstract class MyAbstractEntity implements Comparable<MyAbstractEntity> { 

該類反過來有相當多的子類,恰似這個:

@Entity 
@DiscriminatorValue("BAR") 
public class MyEntity extends MyAbstractEntity implements MyInterface { 

約有一半的子類實現「MyInterface」。

我有一個標準,我有興趣只從實現該接口的類中獲取對象。 當我定義我的標準是這樣的:

Criteria criteria = getSession().createCriteria(MyInterface.class) 

Hibernate的轉身,併產生一個DB-呼籲接口和DB-傢伙的每個實現去堅果。我希望Hibernate能夠將其轉化爲在DISCRIMINATOR列中使用「in」子句的內容,而不是爲每個實現創建一個單獨的調用。

我試過用google搜索這個,但不幸的是我的結果被我的查詢包含「休眠」,「標準」和「接口」的事實所污染,並且我不斷碰到頁面,解釋API或演示基本的例子。

我知道我可以在「MyAbstractEntity」而不是「MyInterface」上創建條件並刪除不想要的結果,但我希望在數據庫中進行此過濾。

有沒有辦法告訴Hibernate,我希望在一個單一的數據庫調用一切?

回答

0

我不能讓Nizet的解決方案來工作,所以我做的稍微骯髒的方式是:

Restrictions.sqlRestriction("{alias}.DISCRIMINATOR in (" + discriminatorValues + ")") 

其中discriminatorValues是在靜態塊初始化靜態字段使用Spring助手類。

Set<Class <? extends MyAbstractEntity>> result = new HashSet<Class <? extends MyAbstractEntity>>(); 

    ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true); 
    provider.addIncludeFilter(new AssignableTypeFilter(MyInterface.class)); 
    Set<BeanDefinition> components = provider.findCandidateComponents("path/to/package/with/subclasses"); 
    for (BeanDefinition component : components) { 
     Class<?> clazz = null; 
     try { 
      clazz = Class.forName(component.getBeanClassName()); 
     } catch (ClassNotFoundException e) { 
      ; //stuff some WTF-message into the logger 
     } 

     result.add((Class<? extends MyAbstractEntity>) clazz); 
    } 

    String sep = ""; 
    for (Class<? extends MyAbstractEntity> o : result) { 
     discriminatorValues += sep + "'" + o.getAnnotation(DiscriminatorValue.class).value() + "'"; 
     sep = ","; 
    } 

不是一種解決方案,我想出去,但由此產生的SQL看起來像我想它... (和接口的新的實現將包括在從沒有進一步的動作查詢未來的開發者)

1

你可以在隱class財產使用in條款:

criteria.add(Restrictions.in("myAbstractEntity.class", 
          new Class[] {MyFirstSubClass.class, MySecondSubClass.class})); 

我有蟲子這些在過去,這裏的課程必須由鑑別器值來代替,但我不」不要記住這個錯誤發生的時間以及是否已經修復。所以,你可以有使用

criteria.add(Restrictions.in("myAbstractEntity.class", 
          new String[] {MyFirstSubClass.DISCRIMINATOR_VALUE, MySecondSubClass.DISCRIMINATOR_VALUE})); 
+0

但是,我不得不在任何時候新的子類開始實現接口的時候改變限制嗎?我們正在坐在一個巨大的代碼庫中,我們即將交付維護,我試圖避免一個解決方案,它需要他們以某種方式知道他們必須去每次新子類開始實施時更新我的​​限制界面。我想我可以結合你的解決方案和一些反思魔術來發現哪些子類將被包含在運行時,但是我更喜歡Hibernate是否可以爲我「處理它」。 – ivarni

+0

這確實是一個問題。我不確定是否有神奇的Hibernate解決方案,儘管 –

+0

這就是我所擔心的,然後我可能會考慮一些與您的解決方案相結合的思考。謝謝。 – ivarni