
net.croz.nrich.search.repository.JpaSearchExecutor Maven / Gradle / Ivy
/*
* Copyright 2020-2023 CROZ d.o.o, the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package net.croz.nrich.search.repository;
import net.croz.nrich.search.api.model.SearchConfiguration;
import net.croz.nrich.search.api.repository.SearchExecutor;
import net.croz.nrich.search.support.JpaQueryBuilder;
import net.croz.nrich.search.util.QueryUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.transaction.annotation.Transactional;
import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaQuery;
import java.util.List;
import java.util.Optional;
// named like this so it is not picked up automatically by jpa auto configuration (executor suffix is from QueryDsl integration)
@Transactional(readOnly = true)
public class JpaSearchExecutor implements SearchExecutor {
private final EntityManager entityManager;
private final Class domainClass;
private final JpaQueryBuilder queryBuilder;
public JpaSearchExecutor(EntityManager entityManager, JpaEntityInformation entityInformation) {
this.entityManager = entityManager;
domainClass = entityInformation.getJavaType();
queryBuilder = new JpaQueryBuilder<>(entityManager, entityInformation.getJavaType());
}
@Override
public Optional findOne(R request, SearchConfiguration searchConfiguration) {
CriteriaQuery query = queryBuilder.buildQuery(request, searchConfiguration, Sort.unsorted());
try {
return Optional.of(entityManager.createQuery(query).getSingleResult());
}
catch (NoResultException ignored) {
return Optional.empty();
}
}
@Override
public List findAll(R request, SearchConfiguration searchConfiguration) {
CriteriaQuery query = queryBuilder.buildQuery(request, searchConfiguration, Sort.unsorted());
return entityManager.createQuery(query).getResultList();
}
@Override
public List findAll(R request, SearchConfiguration searchConfiguration, Sort sort) {
CriteriaQuery query = queryBuilder.buildQuery(request, searchConfiguration, sort);
return entityManager.createQuery(query).getResultList();
}
@Override
public Page findAll(R request, SearchConfiguration searchConfiguration, Pageable pageable) {
CriteriaQuery query = queryBuilder.buildQuery(request, searchConfiguration, pageable.getSort());
TypedQuery
typedQuery = entityManager.createQuery(query);
if (pageable.isPaged()) {
typedQuery.setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize());
return PageableExecutionUtils.getPage(typedQuery.getResultList(), pageable, () -> executeCountQuery(request, searchConfiguration));
}
return new PageImpl<>(typedQuery.getResultList());
}
@Override
public long count(R request, SearchConfiguration searchConfiguration) {
return executeCountQuery(request, searchConfiguration);
}
@Override
public boolean exists(R request, SearchConfiguration searchConfiguration) {
CriteriaQuery query = queryBuilder.buildExistsQuery(request, searchConfiguration);
return entityManager.createQuery(query).setMaxResults(1).getResultList().size() == 1;
}
@Override
public Class getDomainClass() {
return domainClass;
}
private long executeCountQuery(R request, SearchConfiguration searchConfiguration) {
CriteriaQuery countQuery = queryBuilder.buildCountQuery(request, searchConfiguration);
List totals = entityManager.createQuery(countQuery).getResultList();
return QueryUtil.toCountResult(totals);
}
}