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>)
。 我应该如何改变? 我想获得一个只有ID
和VERSION
字段的typesT
对象,而其他的都是null
。
typesT
扩展了具有这两个字段的AbstractEntity
。
entityClazz
是T.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
首先,我不明白为什么你只想要一个只有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它们。 再次,我不确定我能想到的情况下,我想这样做。