JPA和Criteria API – 只select特定的列

我只想select特定的列(例如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>) 。 我应该如何改变? 我想获得一个只有IDVERSION字段的typesT对象,而其他的都是null

typesT扩展了具有这两个字段的AbstractEntity

entityClazzT.class

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不需要是一个实体类。 如果T有一个构造函数,如:

 public T(Long id, Long version) 

那么你可以直接在你的CriteriaQuery构造函数中使用T

 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(); 

看到这个链接进一步参考。

 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

首先,我不明白为什么你只想要一个只有ID和版本的对象,而其他所有的道具都是空的。 然而,这里有一些代码可以为你做(不使用JPA Em,而是使用普通的Hibernate,我假设你可以在JPA中find等价的东西,或者简单地从它的代理中获得Hibernate Session obj 从EJB访问Hibernate Session使用EntityManager ):

 List<T> results = session.createCriteria(entityClazz) .setProjection( Projections.projectionList() .add( Property.forName("ID") ) .add( Property.forName("VERSION") ) ) .setResultTransformer(Transformers.aliasToBean(entityClazz); .list(); 

这将返回一个对象列表,其ID和版本集合以及所有其他的道具为空,因为aliasToBean变换器将无法find它们。 再次,我不确定我能想到的情况下,我想这样做。