gpt4 book ai didi

java - 使用 QuerydslJpaPredicateExecutor 替换已弃用的 QuerydslJpaRepository 失败

转载 作者:行者123 更新时间:2023-12-02 12:26:19 27 4
gpt4 key购买 nike

我需要一些支持自定义 QueryDSL 的查询方法,并遵循 this SO answer .

效果很好,但升级到 Spring Boot 2.1(升级 Spring Data)后,我发现 QuerydslJpaRepository 已被弃用。只需将其替换为 QuerydslJpaPredicateExecutor 即可 - documentation告诉我使用 - 会导致错误:

Caused by: java.lang.IllegalArgumentException: Object of class [...ProjectingQueryDslJpaRepositoryImpl] must be an instance of interface org.springframework.data.jpa.repository.support.JpaRepositoryImplementation

...但是实现 JpaRepositoryImplementation 意味着我必须实现所有标准 CRUD 方法,这显然是我不想要的。因此,如果我从 @EnableJpaRepositories 中删除 repositoryBaseClass 配置,将其视为具有实现的存储库片段,它将尝试实例化该片段,即使它标记为@NoRepositoryBean,给我错误:

Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.Optional ProjectingQueryDslJpaRepository.findOneProjectedBy(com.querydsl.core.types.Expression,com.querydsl.core.types.Predicate)! At least 1 parameter(s) provided but only 0 parameter(s) present in query.

...

Caused by: java.lang.IllegalArgumentException: At least 1 parameter(s) provided but only 0 parameter(s) present in query.

来源的精简版本:

@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);
}
}
}

最佳答案

对于 Spring Boot 2.1.1,以下解决方案可能会对您有所帮助。关键是扩展JpaRepositoryFactory并重写方法getRepositoryFragments(RepositoryMetadatametadata)。在此方法中,您可以为任何自定义存储库提供基本(或更具体的片段)实现,每个扩展存储库都应采用该实现。

让我给你举个例子:

QueryableReadRepository:

@NoRepositoryBean
public interface QueryableReadRepository<T> extends Repository<T, String> {

List<T> findAll(Predicate predicate);

List<T> findAll(Sort sort);

List<T> findAll(Predicate predicate, Sort sort);

List<T> findAll(OrderSpecifier<?>... orders);

List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);

Page<T> findAll(Pageable page);

Page<T> findAll(Predicate predicate, Pageable page);

Optional<T> findOne(Predicate predicate);

boolean exists(Predicate predicate);
}

以下界面组合了不同的存储库。

数据存储库:

@NoRepositoryBean
public interface DataRepository<T>
extends CrudRepository<T, String>, QueryableReadRepository<T> {
}

现在您的特定域存储库可以从 DataRepository 扩展:

@Repository
public interface UserRepository extends DataRepository<UserEntity> {

}

QueryableReadRepositoryImpl:

@Transactional
public class QueryableReadRepositoryImpl<T> extends QuerydslJpaPredicateExecutor<T>
implements QueryableReadRepository<T> {

private static final EntityPathResolver resolver = SimpleEntityPathResolver.INSTANCE;

private final EntityPath<T> path;
private final PathBuilder<T> builder;
private final Querydsl querydsl;

public QueryableReadRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager, resolver, null);
this.path = resolver.createPath(entityInformation.getJavaType());
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
this.querydsl = new Querydsl(entityManager, builder);
}

@Override
public Optional<T> findOne(Predicate predicate) {
return super.findOne(predicate);
}

@Override
public List<T> findAll(OrderSpecifier<?>... orders) {
return super.findAll(orders);
}

@Override
public List<T> findAll(Predicate predicate, Sort sort) {
return executeSorted(createQuery(predicate).select(path), sort);
}

@Override
public Page<T> findAll(Predicate predicate, Pageable pageable) {
return super.findAll(predicate, pageable);
}

@Override
public List<T> findAll(Predicate predicate) {
return super.findAll(predicate);
}

public List<T> findAll(Sort sort) {
return executeSorted(createQuery().select(path), sort);
}

@Override
public Page<T> findAll(Pageable pageable) {
final JPQLQuery<?> countQuery = createCountQuery();
JPQLQuery<T> query = querydsl.applyPagination(pageable, createQuery().select(path));

return PageableExecutionUtils.getPage(
query.distinct().fetch(),
pageable,
countQuery::fetchCount);
}

private List<T> executeSorted(JPQLQuery<T> query, Sort sort) {
return querydsl.applySorting(sort, query).distinct().fetch();
}
}

CustomRepositoryFactoryBean:

public class CustomRepositoryFactoryBean<T extends Repository<S, I>, S, I>
extends JpaRepositoryFactoryBean<T, S, I> {

public CustomRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}

protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new CustomRepositoryFactory(entityManager);
}

自定义存储库工厂:

public class CustomRepositoryFactory extends JpaRepositoryFactory {

private final EntityManager entityManager;

public CustomRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}

@Override
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
RepositoryFragments fragments = super.getRepositoryFragments(metadata);

if (QueryableReadRepository.class.isAssignableFrom(
metadata.getRepositoryInterface())) {

JpaEntityInformation<?, Serializable> entityInformation =
getEntityInformation(metadata.getDomainType());

Object queryableFragment = getTargetRepositoryViaReflection(
QueryableReadRepositoryImpl.class, entityInformation, entityManager);

fragments = fragments.append(RepositoryFragment.implemented(queryableFragment));
}

return fragments;
}

主类:

@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
public class App {
}

这样做的优点是您只需为自定义存储库提供一个(片段)实现。基本存储库实现仍然是 Spring 的默认实现。该示例提供了一个新的存储库,但您也可以在 CustomRepositoryFactory 中覆盖 QuerydslPredicateExecutor 的默认实现

关于java - 使用 QuerydslJpaPredicateExecutor 替换已弃用的 QuerydslJpaRepository 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53083047/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com