2017-02-09 59 views
0

我有一個類水果,一類延伸水果的香蕉和一類擴展香蕉的類YellowBanana。 YellowBanana有一個叫「美味」的領域。如果我想基於仿製藥,我發現了以下異常訪問「美味」中查詢:hibernate無法找到派生類中的字段(懷疑爲泛型)

Unable to locate Attribute with the the given name [tasty] on this ManagedType [Fruit] 

代碼的簡化版本是這樣的:

@MappedSuperclass 
    public abstract class Fruit implements Serializable 
    { 
    } 

    @Entity 
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
    public class Banana extends Fruit 
    { 
    } 

    @Entity 
    public class YellowBanana extends Banana 
    { 
     private boolean tasty = false; 
    } 

    public abstract class GenericDao<T extends Fruit> 
    { 
     public List<T> getObjects(Filter filter /* some criteria passed here */) 
     { 
      EntityManager entityManager = getEntityManager(); 
      CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
      CriteriaQuery<T> query = builder.createQuery(getPersistentClass()); 
      Root<T> root = query.from(getPersistentClass()); 

      List<Predicate> predicates = getFilterQueryRestrictions(root, builder, filter); 
     if (predicates != null && !predicates.isEmpty()) 
      query.where(predicates.toArray(new Predicate[] {})); 

      return entityManager.createQuery(query).getResultList(); 
     } 

     private Class<T> getPersistentClass() 
     { 
      return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
     } 
    } 

    public class BananaDao extends GenericDao<Banana> 
    { 
     @Override 
     protected List<Predicate> getFilterQueryRestrictions(Root<Banana> root, CriteriaBuilder builder, 
     Filter filter) 
     { 
      List<Predicate> restrictions = new ArrayList<Predicate>(); 

      if (filter.forceTasty) 
       // The exception is on the following line on root.get: 
       restrictions.add(builder.equal(root.get("tasty"), 1)); 

      return restrictions; 
     } 
    } 

,你可以看到我的目標是有一個通用的DAO,可以執行Fruit對象的所有CRUD操作。對於派生實體,我創建了實際的DAO類(在本例中爲BananaDao)。 getPersistentClass()返回實際的泛型類型。直到我通過派生實例(在本例中爲YellowBanana)之前,DAO的這種通用方法至今一直在所有操作中都非常精美。

當然這只是一個簡短的例子。現實中的果實是我所有物質的基礎類別(有很多)。我如何讓Hibernate找到「美味」字段的映射?

回答

-1

您應該添加getter和setter該字段,並且還使用註釋

@Column(name="tasty") 
private boolean tasty = false; 

public boolean isTasty(){ 
return tasty; 
} 

public void setTasty(boolean tasty){ 
this.tasty = tasty; 
} 
+1

這不會解決用戶的問題。 – Naros

0

喜歡你的DAO代碼預期tasty屬性不Banana定義的映射。您只在擴展類YellowBanana上定義它,它是您的層次結構中適用的唯一實體類型。

如果tasty被提供給兩個BananaYellowBanana,你應該把它定義既可以作爲你的Banana實體映射超類的一部分或作爲一部分,你的代碼會工作得很好。

+0

但是Hibernate生成的「bananas」表包含了「tasty」字段,所以Hibernate正在正確地找到該字段!當我將一個yellowBanana實例傳遞給該DAO時,Hibernate知道它是一個派生對象,它存儲了「tasty」字段的值。這就是爲什麼我不明白爲什麼當我將它傳遞給root.get()時無法找到它。 – Wombat

+0

然後你的問題中的代碼應該改變,以反映你現有的實體配置,因爲你在'YellowBanana'上指定'tastey'而不是在'Banana'超級類型上。 – Naros

+0

我剛剛測試了代碼,因爲它出現在你的問題中,代碼因爲我提出的原因而失敗。如果代碼反映之前的評論,它的工作原理。我相信你應該再次檢查你的代碼。 – Naros