如何使用Spring数据JPA实现对可选字段的搜索?我已经在多个地方进行了研究,但没有任何帮助。
答案 0 :(得分:0)
经过一段时间的反复试验,我得以实现对可选字段的搜索。
1st)我使用JpaSpecificationExecutor接口扩展了存储库
package br.mp.mpce.sge.repository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import br.mp.mpce.sge.domain.Documento;
import br.mp.mpce.sge.domain.Setor;
@Repository
public interface DocumentoRepository extends JpaRepository<Documento, Integer>, JpaSpecificationExecutor<Documento> {
Page<Documento> findPageBySetorCadastro(Setor setor, Pageable pageRequest);
}
2)我实现了根据搜索参数返回“规格”的方法。
package br.mp.mpce.sge.specifications;
import java.time.LocalDateTime;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;
import br.mp.mpce.sge.domain.Documento;
import br.mp.mpce.sge.domain.Setor;
public final class DocumentoSpecification {
public static Specification<Documento> byCodigo(Integer codigo) {
return new Specification<Documento>() {
private static final long serialVersionUID = -4943925466558950754L;
@Override
public Predicate toPredicate(Root<Documento> root, CriteriaQuery<?> query,
CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.equal(root.get("codigo"), codigo);
}
};
}
public static Specification<Documento> byAno(String ano) {
return new Specification<Documento>() {
private static final long serialVersionUID = 8333055743400529192L;
@Override
public Predicate toPredicate(Root<Documento> root, CriteriaQuery<?> query,
CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.equal(root.get("ano"), ano);
}
};
}
public static Specification<Documento> byDataInicial(LocalDateTime dataInicial) {
return new Specification<Documento>() {
private static final long serialVersionUID = -9172458840598392417L;
@Override
public Predicate toPredicate(Root<Documento> root, CriteriaQuery<?> query,
CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.greaterThanOrEqualTo(root.get("dataCadastro"), dataInicial);
}
};
}
public static Specification<Documento> byDataFinal(LocalDateTime dataFinal) {
return new Specification<Documento>() {
private static final long serialVersionUID = 1422089735211883866L;
@Override
public Predicate toPredicate(Root<Documento> root, CriteriaQuery<?> query,
CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.lessThanOrEqualTo(root.get("dataCadastro"), dataFinal);
}
};
}
public static Specification<Documento> bySetor(Setor setor) {
return new Specification<Documento>() {
private static final long serialVersionUID = -2336742358257555013L;
@Override
public Predicate toPredicate(Root<Documento> root, CriteriaQuery<?> query,
CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.equal(root.get("setorCadastro"), setor);
}
};
}
}
3º)我实现了服务方法类。
public Page<Documento> findByFields(Integer codigo, String ano, String dataInicio, String dataFinal, Integer page,
Integer lines, String direction, String orderBy) {
UsuarioSS usuarioSS = UsuarioServiceImpl.authenticated();
if (usuarioSS == null) {
throw new PersonalizedAutorizationException("Acesso negado - Usuario deve estar autenticado");
}
Usuario usuario = usuarioService.findById(usuarioSS.getId());
PageRequest pageRequest = PageRequest.of(page, lines, Direction.fromString(direction), orderBy);
Specification<Documento> specification = DocumentoSpecification.bySetor(usuario.getSetor());
if (codigo != null) {
specification = specification.and(DocumentoSpecification.byCodigo(codigo));
}
if (ano != null) {
specification = specification.and(DocumentoSpecification.byAno(ano));
}
if (dataInicio != null) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate localDateInicio;
localDateInicio = LocalDate.parse(dataInicio, formatter);
LocalDateTime localDateTimeInicio = localDateInicio.atStartOfDay();
specification = specification.and(DocumentoSpecification.byDataInicial(localDateTimeInicio));
}
if (dataFinal != null) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate localDateFinal;
localDateFinal = LocalDate.parse(dataFinal, formatter);
LocalDateTime localDateTimeFinal = localDateFinal.atStartOfDay();
specification = specification.and(DocumentoSpecification.byDataFinal(localDateTimeFinal));
}
Page<Documento> pageDoc = documentoRepository.findAll(specification, pageRequest);
if (pageDoc.getContent().isEmpty()) {
throw new PersonalizedObjectNotFoundException(super.messageSource.getMessage("error.notFound",
new String[] { super.messageSource.getMessage(
StringUtils.uncapitalize(super.getEntityClass().getSimpleName()), null,
StringUtils.uncapitalize(getEntityClass().getSimpleName()), null) },
"error.notFound", null));
}
return pageDoc;
}
4º)在restcontroller中实现了搜索方法。
@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<Page<Documento>> findPageByFields(
@RequestParam(value = "codigo", required = false) Integer codigo,
@RequestParam(value = "ano", required = false) String ano,
@RequestParam(value = "dataInicio", required = false) String dataInicio,
@RequestParam(value = "dataFinal", required = false) String dataFinal,
@RequestParam(value = "page", defaultValue = "0") Integer page,
@RequestParam(value = "lines", defaultValue = "10") Integer lines,
@RequestParam(value = "direction", defaultValue = "DESC") String direction,
@RequestParam(value = "orderBy", defaultValue = "dataCadastro") String orderBy) {
Page<Documento> pageDocumento = documentoService.findByFields(codigo, ano, dataInicio, dataFinal, page, lines,
direction, orderBy);
return ResponseEntity.ok().body(pageDocumento);
}