Вопрос по java, sql, jpa-2.0, jpql, criteria-api – API критериев: фильтр по типу класса

4

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

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», и здесь я также не знаю, как написать его так, чтобы возвращался только определенный тип ...

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

РЕДАКТИРОВАТЬ: перенес второй вопрос взапрос критериев: нечеткие списки результатов и удалены различные в коде (это не сработало)

Я могу сделать это, когда я определяю сущности как root. Тогда я могу точно определить класс. Проблема здесь в том, что я получаю доступ к объектам через атрибутowningEntities подходящих свойств. И этот атрибут имеет тип List <AbstractEntity>. Jogi
Что, если бы этот запрос был параметризован с использованием обобщений? Тогда вы могли бы сказать, хотите ли вы AbstractEntity или ConcreteEntity во время компиляции (не уверен, имеет ли это смысл) Leo

Ваш Ответ

2   ответа
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);
1

который я нашел до сих пор, - это создать перечисление со значением для каждого класса. Результирующий критерий запроса

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)

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

Похожие вопросы