API JPA & Criteria - выберите только определенные столбцы
Я хотел бы выбрать только определенные столбцы (например, SELECT a FROM b
). У меня есть общий DAO, и я придумал следующее:
public List<T> getAll(boolean idAndVersionOnly) {
CriteriaBuilder builder = manager.getCriteriaBuilder();
CriteriaQuery<T> criteria = builder.createQuery(entityClazz);
Root<T> root = criteria.from(entityClazz);
if (idAndVersionOnly) {
criteria.select(root.get("ID").get("VERSION")); // HERE IS ERROR
} else {
criteria.select(root);
}
return manager.createQuery(criteria).getResultList();
}
И ошибка:
The method select(Selection<? extends T>) in the type CriteriaQuery<T> is not applicable for the arguments (Path<Object>)
. Как мне это изменить? Я хочу получить объект типа T
, который имеет только поля ID
и VERSION
, а все остальные - null
.
Тип T
extends AbstractEntity
, который имеет эти 2 поля.
entityClazz
T.class
.
Ответы
Ответ 1
Один из способов JPA для получения только определенных столбцов - это запросить объект Tuple.
В вашем случае вам нужно написать что-то вроде этого:
CriteriaQuery<Tuple> cq = builder.createTupleQuery();
// write the Root, Path elements as usual
Root<EntityClazz> root = cq.from(EntityClazz.class);
cq.multiselect(root.get(EntityClazz_.ID), root.get(EntityClazz_.VERSION)); //using metamodel
List<Tuple> tupleResult = em.createQuery(cq).getResultList();
for (Tuple t : tupleResult) {
Long id = (Long) t.get(0);
Long version = (Long) t.get(1);
}
Другой подход возможен, если у вас есть класс, представляющий результат, например T
в вашем случае. T
не обязательно должен быть классом Entity. Если T
имеет конструктор типа:
public T(Long id, Long version)
то вы можете использовать T
непосредственно в своем конструкторе CriteriaQuery
:
CriteriaQuery<T> cq = builder.createQuery(T.class);
// write the Root, Path elements as usual
Root<EntityClazz> root = cq.from(EntityClazz.class);
cq.multiselect(root.get(EntityClazz_.ID), root.get(EntityClazz_.VERSION)); //using metamodel
List<T> result = em.createQuery(cq).getResultList();
Подробнее см. ссылку .
Ответ 2
cq.select(cb.construct(entityClazz.class, root.get("ID"), root.get("VERSION"))); // HERE IS NO ERROR
https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/Criteria#Constructors
Ответ 3
Прежде всего, я не понимаю, почему вы хотите, чтобы объект имел только ID и версию, а все остальные реквизиты были нулями. Тем не менее, вот какой-то код, который сделает это для вас (который не использует JPA Em, но обычный Hibernate. Я предполагаю, что вы можете найти эквивалентность в JPA или просто получить сеанс Hibernate Session из делегата em
Доступ к сеансу Hibernate из EJB с помощью EntityManager
):
List<T> results = session.createCriteria(entityClazz)
.setProjection( Projections.projectionList()
.add( Property.forName("ID") )
.add( Property.forName("VERSION") )
)
.setResultTransformer(Transformers.aliasToBean(entityClazz);
.list();
Это вернет список объектов, у которых их идентификатор и версия установлены, а все остальные реквизиты равны нулю, поскольку трансформатор aliasToBean не сможет их найти. Опять же, я не уверен, что могу подумать о ситуации, в которой я хотел бы это сделать.