2017-02-09 21 views
0

У меня есть класс Fruit, класс Banana, который расширяет Fruit и класс YellowBanana, который расширяет Банан. У YellowBanana есть поле под названием «вкусно». Если я пытаюсь получить доступ к «вкусно» в запросе на основе дженериков я получаю следующее исключение:Спящий режим не может найти поле в производном классе (предположительно дженерики)

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, который выполняет все операции CRUD для объектов Fruit. Для производных я создаю фактические классы DAO (BananaDao в этом примере). getPersistentClass() возвращает фактический общий тип. Этот общий способ DAO работает прекрасно до сих пор со всеми операциями, пока я не передал производный экземпляр (YellowBanana в этом примере).

Конечно, это лишь краткий пример. Фрукты на самом деле являются базовым классом всех моих entites (их много). Как я могу заставить Hibernate найти карту для «вкусного» поля?

ответ

-1

Вы должны добавить геттер и сеттер для этого поля, а также сопоставить его с помощью аннотаций

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

public boolean isTasty(){ 
return tasty; 
} 

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

Это не решит проблему пользователя. – Naros

0

Атрибут tasty не определен на Banana как ваш код DAO ожидает. Вы только определили его в расширенном классе, YellowBanana, который является единственным типом объекта, где он применим в вашей иерархии.

Если tasty должна быть доступна как Banana и YellowBanana, вы должны определить его либо как часть вашего Banana лица или в качестве части преобразованного суперкласса типа и код будет работать нормально.

+0

Но таблица «бананов», которая генерирует Hibernate, содержит «вкусное» поле, поэтому Hibernate правильно находит это поле! Когда я передаю экземпляр yellowBanana, этот DAO Hibernate знает, что это производный объект, и он сохраняет значение «вкусного» поля. Вот почему я не понимаю, почему он не может найти его, когда я передаю его root.get(). – Wombat

+0

Затем код в вашем вопросе должен быть изменен, чтобы отразить существующие конфигурации сущностей, потому что вы указали 'tastey' на' YellowBanana', а не на супер-тип 'Banana'. – Naros

+0

Я только что проверил код, как он появляется в вашем вопросе, этот код не подходит по той причине, которую я представил. Если код отражает предыдущий комментарий, он работает. Я считаю, что вы должны еще раз просмотреть свой код. – Naros