Мне потребовались некоторые настраиваемые методы запросов с поддержкой QueryDSL, и я выполнил этот ТАК ответ.
Это отлично сработало, но после обновления до Spring Boot 2.1 (который обновляет Spring Data) я обнаружил, что QuerydslJpaRepository
устарел. Просто заменив его на QuerydslJpaPredicateExecutor
- что документация говорит мне использовать - приводит к ошибке:
Вызвано: java.lang.IllegalArgumentException: объект класса [... ProjectingQueryDslJpaRepositoryImpl] должен быть экземпляром интерфейса org.springframework.data.jpa.repository.support.JpaRepositoryImplementation
... но реализация JpaRepositoryImplementation
будет означать, что мне придется реализовать все стандартные методы CRUD, которые мне явно не нужны. Поэтому, если я удалю конфигурацию repositoryBaseClass
из @EnableJpaRepositories
, чтобы рассматривать это как фрагмент репозитория с реализацией, он попытается создать экземпляр фрагмента, даже если он помечен @NoRepositoryBean
, что даст мне ошибку:
Вызвано: java.lang.IllegalArgumentException: не удалось создать запрос для метода public abstract java.util.Optional ProjectingQueryDslJpaRepository.findOneProjectedBy (com.querydsl.core.types.Expression, com.querydsl.core.types.Predicate)! Предусмотрен как минимум 1 параметр, но в запросе присутствует только 0 параметров.
...
Вызвано: java.lang.IllegalArgumentException: предоставлен не менее 1 параметра (ов), но в запросе присутствует только 0 параметров.
Сокращенная версия источника:
@Configuration
@EnableJpaRepositories(basePackageClasses = Application.class, repositoryBaseClass = ProjectingQueryDslJpaRepositoryImpl.class)
@EnableTransactionManagement
@EnableJpaAuditing
@RequiredArgsConstructor(onConstructor = @__({@Autowired}))
public class DatabaseConfig {}
_
@NoRepositoryBean
public interface ProjectingQueryDslJpaRepository<T> extends QuerydslBinderCustomizer<EntityPath<T>>, QuerydslPredicateExecutor<T> {
@NonNull
<P> Page<P> findPageProjectedBy(@NonNull Expression<P> factoryExpression, Predicate predicate,
@NonNull Pageable pageable);
@NonNull
<P> Optional<P> findOneProjectedBy(@NonNull Expression<P> factoryExpression, @NonNull Predicate predicate);
@Override
default void customize(@NonNull QuerydslBindings bindings, @NonNull EntityPath<T> root){
bindings.bind(String.class).first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
}
}
_
public class ProjectingQueryDslJpaRepositoryImpl<T, ID extends Serializable> extends QuerydslJpaRepository<T, ID>
implements ProjectingQueryDslJpaRepository<T> {
private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
private final EntityPath<T> path;
private final Querydsl querydsl;
public ProjectingQueryDslJpaRepositoryImpl(@NonNull JpaEntityInformation<T, ID> entityInformation, @NonNull EntityManager entityManager) {
this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
}
public ProjectingQueryDslJpaRepositoryImpl(@NonNull JpaEntityInformation<T, ID> entityInformation, @NonNull EntityManager entityManager,
@NonNull EntityPathResolver resolver) {
super(entityInformation, entityManager, resolver);
this.path = resolver.createPath(entityInformation.getJavaType());
PathBuilder<T> builder = new PathBuilder<>(path.getType(), path.getMetadata());
this.querydsl = new Querydsl(entityManager, builder);
}
@Override
public <P> Page<P> findPageProjectedBy(@NonNull Expression<P> factoryExpression, Predicate predicate,
@NonNull Pageable pageable) {
final JPQLQuery<?> countQuery = createCountQuery(predicate);
JPQLQuery<P> query = querydsl.applyPagination(pageable, createQuery(predicate).select(factoryExpression));
return PageableExecutionUtils.getPage(query.fetch(), pageable, countQuery::fetchCount);
}
@Override
public <P> Optional<P> findOneProjectedBy(@NonNull Expression<P> factoryExpression, @NonNull Predicate predicate) {
try {
return Optional.ofNullable(createQuery(predicate).select(factoryExpression).from(path).fetchOne());
} catch (NonUniqueResultException ex) {
throw new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
}
}
}