Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA & Criteria API - Select only specific columns

I would like to select only specific columns (ex. SELECT a FROM b). I have a generic DAO and what I came up with is:

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

And the error is: The method select(Selection<? extends T>) in the type CriteriaQuery<T> is not applicable for the arguments (Path<Object>). How should I change that? I want to get a type T object that has only ID and VERSION fields, and all others are null.

Type T extends AbstractEntity which has those 2 fields.

entityClazz is T.class.

like image 515
BartoszCichecki Avatar asked Sep 27 '12 09:09

BartoszCichecki


2 Answers

One of the JPA ways for getting only particular columns is to ask for a Tuple object.

In your case you would need to write something like this:

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

Another approach is possible if you have a class representing the result, like T in your case. T doesn't need to be an Entity class. If T has a constructor like:

public T(Long id, Long version) 

then you can use T directly in your CriteriaQuery constructor:

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

See this link for further reference.

like image 145
perissf Avatar answered Sep 22 '22 21:09

perissf


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

like image 22
EduardoRamirez Avatar answered Sep 25 '22 21:09

EduardoRamirez