We can select specific columns by writing custom @Query methods in our Repository Interface. However, I don't want to write so many methods for different properties.
I tried this, but it returns the entire object all the time.
public class MySpecifications {
public static Specification<MyInfo> propertiesWithId(final String[] properties, final Object id, final String idProperty)
{
return new Specification<MyInfo>() {
@Override
public Predicate toPredicate(Root<MyInfo> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
query = cb.createTupleQuery(); //tried cb.createQuery(MyInfo.class); as well
List<Selection<? extends Object>> selectionList = new ArrayList<Selection<? extends Object>>();
for (String property : properties) {
Selection<? extends Object> selection = root.get(property);
selectionList.add(selection);
}
return query.multiselect(selectionList).where(cb.equal(root.get(idProperty), id)).getRestriction();
}
};
}
}
used as:
MyInfo findOne(Specification(properties,idValue, idProperty));
Is this the correct way? Where is the mistake?
The current spring data jpa specification executor is limited to criteria in the where clause, so you can change the selected columns, it's limited to full entities only. You'll have to go with a custom repository implementation, or move to named queries-
Spring Data JPA and Querydsl to fetch subset of columns using bean/constructor projection
Specifications are abstractions over where clauses. Due to the design of the JPA criteria API you can all kinds of stuff in Specification but the behaviour of any side effect apart from declaring a where clause is undefined.
If you want to control the select list you can either use query derivation with projections and the very limited query support or construct complete custom queries in a custom method.
This method returns single entity matching given specification. Please check here
According to my understanding this is the correct way. U can access the properties of the entity as normal (Eg. MyInfo.getIdProperty())