You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何扩展QuerydslJpaPredicateExecutor并实现Spring构造参数自动注入?

你遇到的错误是因为JpaEntityInformation并非Spring容器中的Bean,它是由Spring Data JPA的仓库工厂动态创建的,无法通过常规依赖注入获取;同时你的自定义实现类SliceableRepositoryImpl未被Spring Data JPA的仓库工厂正确识别,导致无法自动传递构造所需参数。以下是两种可行的解决方案:

解决方案一:自定义全局仓库基类(适用于所有JPA仓库)

适合需要统一修改所有仓库Querydsl查询逻辑的场景,所有JPA仓库都会基于该基类创建。

  1. 创建自定义仓库基类,继承SimpleJpaRepository并实现QuerydslPredicateExecutor:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.Querydsl;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.jpa.repository.support.SimpleEntityPathResolver;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JpaQuery;
import jakarta.persistence.EntityManager;
import java.util.List;
import java.util.Optional;

public class SliceableRepositoryImpl<T, ID> extends SimpleJpaRepository<T, ID> implements QuerydslPredicateExecutor<T> {

    private final EntityManager entityManager;
    private final Querydsl querydsl;

    // 接收仓库工厂提供的构造参数
    public SliceableRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
        var path = SimpleEntityPathResolver.INSTANCE.createPath(entityInformation.getJavaType());
        this.querydsl = new Querydsl(entityManager, new com.querydsl.core.types.dsl.PathBuilder<>(path.getType(), path.getMetadata()));
    }

    // 重写需要修改的Querydsl查询方法
    @Override
    public Page<T> findAll(Predicate predicate, Pageable pageable) {
        // 在这里编写自定义逻辑,比如添加默认过滤条件、修改分页规则等
        JpaQuery<T> query = createQuery(predicate);
        long total = count(predicate);
        List<T> content = querydsl.applyPagination(pageable, query).fetch();
        return new org.springframework.data.domain.PageImpl<>(content, pageable, total);
    }

    // 实现QuerydslPredicateExecutor的其他方法,复用默认逻辑
    @Override
    public Optional<T> findOne(Predicate predicate) {
        return QuerydslJpaPredicateExecutor.super.findOne(predicate);
    }

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

    @Override
    public Iterable<T> findAll(Predicate predicate, com.querydsl.core.types.OrderSpecifier<?>... orders) {
        return QuerydslJpaPredicateExecutor.super.findAll(predicate, orders);
    }

    @Override
    public Iterable<T> findAll(com.querydsl.core.types.OrderSpecifier<?>... orders) {
        return QuerydslJpaPredicateExecutor.super.findAll(orders);
    }

    @Override
    public long count(Predicate predicate) {
        return QuerydslJpaPredicateExecutor.super.count(predicate);
    }

    @Override
    public boolean exists(Predicate predicate) {
        return QuerydslJpaPredicateExecutor.super.exists(predicate);
    }

    // 辅助方法:创建Querydsl查询实例
    private JpaQuery<T> createQuery(Predicate predicate) {
        var path = SimpleEntityPathResolver.INSTANCE.createPath(getDomainClass());
        return new JpaQuery<>(entityManager).select(path).from(path).where(predicate);
    }
}
  1. 在Spring Boot启动类(或配置类)中指定自定义基类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = SliceableRepositoryImpl.class)
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}
  1. 定义仓库接口,继承JpaRepository和QuerydslPredicateExecutor:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;

public interface MysRepository extends JpaRepository<MyEntity, Long>, QuerydslPredicateExecutor<MyEntity> {
}
解决方案二:针对单个仓库的自定义实现(仅修改特定仓库)

如果只需要修改某一个仓库的Querydsl逻辑,可使用这种方式。

  1. 定义自定义方法接口(存放需要重写的方法):
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import com.querydsl.core.types.Predicate;

public interface MysRepositoryCustom {
    Page<MyEntity> findAll(Predicate predicate, Pageable pageable);
}
  1. 创建自定义实现类,继承QuerydslJpaPredicateExecutor并实现自定义接口:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.QuerydslJpaPredicateExecutor;
import org.springframework.data.jpa.repository.support.SimpleEntityPathResolver;
import com.querydsl.core.types.Predicate;
import jakarta.persistence.EntityManager;

public class MysRepositoryImpl extends QuerydslJpaPredicateExecutor<MyEntity> implements MysRepositoryCustom {

    // 接收仓库工厂传递的构造参数
    public MysRepositoryImpl(JpaEntityInformation<MyEntity, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager, SimpleEntityPathResolver.INSTANCE, null);
    }

    @Override
    public Page<MyEntity> findAll(Predicate predicate, Pageable pageable) {
        // 编写自定义查询逻辑,比如添加全局过滤条件
        Predicate modifiedPredicate = predicate.and(QMyEntity.myEntity.isActive.eq(true));
        return super.findAll(modifiedPredicate, pageable);
    }
}
  1. 主仓库接口继承JpaRepository、QuerydslPredicateExecutor和自定义接口:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;

public interface MysRepository extends JpaRepository<MyEntity, Long>, QuerydslPredicateExecutor<MyEntity>, MysRepositoryCustom {
}

关键说明

  • Spring Data JPA会自动识别命名为XxxRepositoryImpl的实现类(对应XxxRepository接口),将自定义方法的逻辑委托给该实现类。
  • JpaEntityInformation、EntityManager等参数由仓库工厂在创建仓库实例时自动传递,无需手动注入,因为它们不是Spring容器中的Bean,而是仓库工厂动态生成的对象。

内容的提问来源于stack exchange,提问作者membersound

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 02:45:36