2014-10-06 2 views
3

Я отношусь к новым реляционным базам данных, и у меня есть некоторые проблемы, связанные с созданием запросов. Сначала я хочу коротко объяснить ситуацию. У меня есть несколько классов сущностей. Все они распространяются на AbstractEntity или EntityProperty. Таким образом, объекты могут иметь свойства и свойства, имеющие собственные объекты, поэтому существует двунаправленное отношение.
Теперь предположим, что ConcreteEntity расширяет AbstractEntity, и я хочу создавать запросы следующим образом: Получить все сущности типа ConcreteEntity, который имеет как минимум свойство с именем, содержащимся в данном списке propertyNames. До сих пор я иметь следующий рабочий критерии запроса:Критерии API: фильтр по типу класса

CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class); 
Root<EntityProperty> property = cq.from(EntityProperty.class); 
Join<EntityProperty, AbstractEntity> entity = property.join(EntityProperty_.owningEntities); 
cq.where(property.get(EntityProperty_.name).in((Object[]) propertyNames)); 
cq.select(entity); 

Но сейчас я хочу только те объекты типа ConcreteEntity. Как я мог это достичь? В JPQL я написал «SELECT entity FROM EntityProperty свойство JOIN property.owningEntities entity», и здесь я также не знаю, как записать его так, как только возвращается конкретный тип ...

Спасибо за ответы заранее !

EDIT: переместил второй вопрос criteria query: indistinct result lists и удалить различны в коде (который не работал)

+0

что делать, если у вас был этот параметр параметризирован с использованием дженериков? Тогда вы могли бы сказать, хотите ли вы, чтобы AbstractEntity или ConcreteEntity во время компиляции (не уверен, что это имеет смысл) – Leo

+0

Я могу это сделать, когда я определяю сущности как root. Тогда я могу осмысленно определить класс. Проблема здесь в том, что я получаю доступ к объектам через атрибут 'owningEntities' свойств фитинга. И этот атрибут имеет тип List . – Jogi

ответ

1

Единственным способом я нашел до сих пор был создать перечисление со значением для каждого класса Полученных критериев query is

CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class); 
Root<EntityProperty> property = cq.from(EntityProperty.class); 
SetJoin<EntityProperty, AbstractEntity> entity = 
       property.join(EntityProperty_.owningEntities); 
cq.where(property.get(EntityProperty_.name).in((Object[]) propertyNames), 
       entity.get(AbstractEntity_.entityType).in(suitableSubTypes)); 
cq.select(entity); 
List<AbstractEntity> resultList = em.createQuery(cq).getResultList(); 

Как вы можете видеть, каждая сущность теперь имеет атрибут entityType. Я также должен каждый раз создавать коллекцию подходящихSubTypes. Другая проблема заключается в том, что возвращаемый тип - List<AbstractEntity>. То, что я хотел был метод подписи, как

public static <T extends AbstractEntity> List<T> 
       getEntities(Class<T> entityClass, String... propertyNames) 

но теперь у меня есть

public static List<AbstractEntity> 
       getEntities(Collection<AbstractEntityType> suitableSubTypes, 
       String... propertyNames) 

Так что я все еще надеюсь, что существует лучшее решение ...

2

Я знаю, что это старый вопрос но на всякий случай кто-то сталкивается с одной и той же проблемой, вот как это можно решить. Вы можете легко фильтровать по типу объекта, как это:

Predicate p = cb.equal(entity.type(), cb.literal(ConcreteEntity.class)); 

где объект может быть путь (Root и Join в комплекте), центибар является объектом CriteriaBuilder. Так что в вашем случае это будет примерно так:

CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class); 
Root<EntityProperty> property = cq.from(EntityProperty.class); 
Join<EntityProperty, AbstractEntity> entity = property.join(EntityProperty_.owningEntities); 
cq.where(cb.and(
    property.get(EntityProperty_.name).in((Object[]) propertyNames), 
    cb.equal(entity.type(), cb.literal.ConcreteEntity.class) 
)); 
cq.select(entity); 

 Смежные вопросы

  • Нет связанных вопросов^_^