#java #spring #spring-boot #jpa #specifications
#java #spring #spring-boot #jpa #спецификации
Вопрос:
Я использую JpaSpecificationExecutor в spring boot, но я не могу получить один столбец или список выбранных столбцов, например, SQL-запрос «Выберите имя, фамилию от студента, где firstname =’abc’;» Я столкнулся с проблемой с JpaSpecificationExecutor, он всегда выдает целую сущность.
My some code added Repository Interface
```
@Repository
public interface PolicyRepository extends JpaRepository<Policy, Long>,JpaSpecificationExecutor<Policy> {
}
public class PredicateSpecification<T> implements Specification<T> {
private static final long serialVersionUID = 1L;
SearchCriteria search_criteria;
public PredicateSpecification(SearchCriteria criteria) {
this.search_criteria = criteria;
}
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<>();
switch (search_criteria.getOperation()) {
case GREATER_THAN:
predicates.add(builder.greaterThan(root.get(search_criteria.getKey()).as(String.class),
builder.literal(search_criteria.getValue().toString())));
break;
case LESS_THAN:
predicates.add(builder.lessThan(root.get(search_criteria.getKey()).as(String.class),
builder.literal(search_criteria.getValue().toString())));
break;
case GREATER_THAN_EQUAL:
predicates.add(builder.greaterThanOrEqualTo(root.get(search_criteria.getKey()).as(String.class),
builder.literal(search_criteria.getValue().toString())));
break;
case LESS_THAN_EQUAL:
predicates.add(builder.lessThanOrEqualTo(root.get(search_criteria.getKey()).as(String.class),
builder.literal(search_criteria.getValue().toString())));
break;
case NOT_EQUAL:
predicates.add(builder.notEqual(root.get(search_criteria.getKey()), search_criteria.getValue()));
break;
case EQUAL:
predicates.add(builder.equal(root.get(search_criteria.getKey()), search_criteria.getValue()));
break;
case MATCH:
predicates.add(builder.like(builder.lower(root.get(search_criteria.getKey())),
"%" search_criteria.getValue().toString().toLowerCase() "%"));
break;
case MATCH_END:
predicates.add(builder.like(builder.lower(root.get(search_criteria.getKey())),
search_criteria.getValue().toString().toLowerCase() "%"));
break;
case MATCH_START:
predicates.add(builder.like(builder.lower(root.get(search_criteria.getKey())),
"%" search_criteria.getValue().toString().toLowerCase()));
break;
case IN:
predicates.add(builder.in(root.get(search_criteria.getKey())).value(search_criteria.getValue()));
break;
case ORDER_BY:
if (search_criteria.getValue().equals(OrderBy.ASC)) {
query.orderBy(builder.asc(root.get(search_criteria.getKey())));
} else if (search_criteria.getValue().equals(OrderBy.DESC)) {
query.orderBy(builder.desc(root.get(search_criteria.getKey())));
}
break;
case GROUP_BY:
query.groupBy(root.get(search_criteria.getKey()));
// query.multiselect(root.get(search_criteria.getKey()), builder.count(root));
break;
default:
break;
}
return builder.and(predicates.toArray(new Predicate[0]));
}
}
public List<Policy> getPolicyByPredicates() throws ParseException {
PredicateSpecification<Policy> psf1 = new PredicateSpecification<Policy>(
(new SearchCriteria("policyName", "test", SearchOperation.MATCH)));
PredicateSpecification<Policy> psf2 = new PredicateSpecification<Policy>(
(new SearchCriteria("isEnable",true, SearchOperation.EQUAL)));
return policyRepo.findAll(Specification.where(psf1).and(psf2));
}
```
above getPolicyByPredicates() method call from controller
and it returns List<Policy> but I want to return only specific columns.
Как можно вернуть конкретный столбец из объекта, используя спецификацию jpa?
Пожалуйста, помогите мне.
Blockquote
Ответ №1:
Не могли бы вы уточнить или привести пример, что вы подразумеваете под «получить один столбец или список выбранных столбцов». Результат вашего запроса будет сопоставлен на основе определенного вами объекта политики. Если вы хотите получить определенное свойство из своего списка, вы можете использовать ‘Map’ из потока после вызова вашего метода getPolicyByPredicates ().
Пример:
List<Policy> result = getPolicyByPredicates();
List<String> lastNames = result.stream()
.map(Policy::getLastName)
.collect(Collectors.toList());
В приведенном выше примере показано только получение «фамилий», но вы все равно можете выбрать, какой столбец вы хотите получить.
Комментарии:
1. Actullay в спецификации выполняет запрос типа «выберите * из политики, где pname =»abc» » но если я хочу создать запрос типа «выберите pname, lastname, isenable из политики, где pname =»abc» » тогда как это можно сделать?
2. и я сталкиваюсь с другой проблемой, которая заключается в том, что select * from имя_таблицы дает ненужную информацию о дочерней таблице. например, в случае, если у одного родителя много дочерних элементов, т.е. Отношение onetomany в родительско-дочерней таблице, и если мы выполняем запрос с использованием спецификации jpa, он возвращает данные родительской и дочерней таблиц, и я думаю, что это создает проблемы с производительностью в больших данных, так как можно решить эту проблему в спецификации JPA.