我想只选择特定列(例如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
扩展AbstractEntity
,其中包含这两个字段。
entityClazz
是T.class
。
答案 0 :(得分:76)
仅获取特定列的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)
然后您可以直接在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();
有关详细信息,请参阅此link。
答案 1 :(得分:8)
cq.select(cb.construct(entityClazz.class, root.get("ID"), root.get("VERSION"))); // HERE IS NO ERROR
答案 2 :(得分:3)
首先,我真的不明白为什么你想要一个只有ID和Version的对象,而所有其他的道具都是null。但是,这里有一些代码会为你做这件事(它不使用JPA Em,而是普通的Hibernate。我假设你可以在JPA中找到等价或者只是从em委托中获取Hibernate Session obj Accessing Hibernate Session from EJB using EntityManager ):
List<T> results = session.createCriteria(entityClazz)
.setProjection( Projections.projectionList()
.add( Property.forName("ID") )
.add( Property.forName("VERSION") )
)
.setResultTransformer(Transformers.aliasToBean(entityClazz);
.list();
这将返回一个对象列表,其中包含ID和Version设置以及所有其他props为null,因为aliasToBean转换器将无法找到它们。再一次,我不确定我能想到我想要这样做的情况。
答案 3 :(得分:-2)
您可以这样做
Session session = app.factory.openSession();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery();
Root<Users> root = query.from(Users.class);
query.select(root.get("firstname"));
String name = session.createQuery(query).getSingleResult();
您可以在其中使用所需列的名称更改“名字”。