Существует обходной путь, который использует каноническую метамодель.
К сожалению, EntityModel, которую мы получаем от productSearchFilterRoot, нам мало помогает, потому что
только дает нам рассматривать как набор. Таким образом, мы не можем запросить Атрибуты IdClass сразу по имени атрибута оттуда.
Но они все равно есть:
//following will contain three attributes that are part of id.
Set<SingularAttribute<? super ProductSearchFilter, ?>> s = model.getIdClassAttributes();
Вместо этого мы перейдем к канонической метамодели. Для этого нам нужен один новый класс, который мы можем реализовать
сами или пусть Хибенате сделает это:
@StaticMetamodel(ProductSearchFilter.class)
public abstract class ProductSearchFilter_ {
public static volatile SingularAttribute<ProductSearchFilter, String> category;
public static volatile SingularAttribute<ProductSearchFilter, String> fdaStatus;
public static volatile SingularAttribute<ProductSearchFilter, String> source;
public static volatile SingularAttribute<ProductSearchFilter, String> name;
public static volatile SingularAttribute<ProductSearchFilter, String> searchColumn;
public static volatile SingularAttribute<ProductSearchFilter, String> productId;
}
И тогда мы будем использовать поля ProductSearchFilter_ в качестве аргумента, чтобы получить в productSearchFilterRoot:
CriteriaBuilder queryBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Tuple> query = queryBuilder.createTupleQuery();
Root<ProductSearchFilter> productSearchFilterRoot = query.from(ProductSearchFilter.class);
query.multiselect(
productSearchFilterRoot.get(ProductSearchFilter_.productId).alias("productId"),
productSearchFilterRoot.get(ProductSearchFilter_.category).alias("category"),
productSearchFilterRoot.get(ProductSearchFilter_.name).alias("name"),
productSearchFilterRoot.get(ProductSearchFilter_.fdaStatus).alias("fdaStatus"));
query.distinct(true);
Поскольку у нас теперь есть метамодель, я также использовал ее для создания выделения для имени, но поскольку он не является частью идентификатора, мы могли бы оставить его как есть:
productSearchFilterRoot.get("name").alias("name"),