Spring Data JPA和Querydsl使用bean/constructor投影获取列的子集

Mur*_*ali 25 jpa querydsl spring-data-jpa

我有一个实体类如下:

@Entity
public class UserDemo implements Serializable {

    @Id
    private Long id;

    private String username;

    private String createdBy;
    @Version
    private int version;

    /***
     *
     * Getters and setters
     */
}
Run Code Online (Sandbox Code Playgroud)


使用Spring Data JPA和Querydsl如何获取仅包含和添加属性的UserDemo页面?我需要使用分页和搜索.总之,我希望得到与之相同的结果idusername

Page<UserDemo> findAll(Predicate predicate, Pageable pageable);
Run Code Online (Sandbox Code Playgroud)

但填充了UserDemo的有限字段.

Mur*_*ali 31

看起来自定义存储库实现是现在的方式,直到spring数据中有类似的东西可用.

我已经浏览了http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.custom-implementations

这是我的实现有效.但是,在Spring-Data-JPA中直接使用此方法会很好

步骤1:共享行为的中间接口

public interface CustomQueryDslJpaRepository <T, ID extends Serializable>
        extends JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {
    /**
     * Returns a {@link org.springframework.data.domain.Page} of entities matching the given {@link com.mysema.query.types.Predicate}.
     * This also uses provided projections ( can be JavaBean or constructor or anything supported by QueryDSL
     * @param constructorExpression this constructor expression will be used for transforming query results
     * @param predicate
     * @param pageable
     * @return
     */
    Page<T> findAll(FactoryExpression<T> factoryExpression, Predicate predicate, Pageable pageable);
}
Run Code Online (Sandbox Code Playgroud)

第2步:实现中间接口

public class CustomQueryDslJpaRepositoryImpl<T, ID extends Serializable> extends QueryDslJpaRepository<T, ID>
        implements CustomQueryDslJpaRepository<T, ID> {

    //All instance variables are available in super, but they are private
    private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;

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

    public CustomQueryDslJpaRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
        this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
    }

    public CustomQueryDslJpaRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager,
                                 EntityPathResolver resolver) {

        super(entityInformation, entityManager);
        this.path = resolver.createPath(entityInformation.getJavaType());
        this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
        this.querydsl = new Querydsl(entityManager, builder);
    }

    @Override
    public Page<T> findAll(FactoryExpression<T> factoryExpression, Predicate predicate, Pageable pageable) {
        JPQLQuery countQuery = createQuery(predicate);
        JPQLQuery query = querydsl.applyPagination(pageable, createQuery(predicate));

        Long total = countQuery.count();
        List<T> content = total > pageable.getOffset() ? query.list(factoryExpression) : Collections.<T> emptyList();

        return new PageImpl<T>(content, pageable, total);
    }
}
Run Code Online (Sandbox Code Playgroud)

步骤3:创建自定义存储库工厂以替换默认工具

public class CustomQueryDslJpaRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
        extends JpaRepositoryFactoryBean<R, T, I> {

    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {

        return new CustomQueryDslJpaRepositoryFactory(entityManager);
    }
    private static class CustomQueryDslJpaRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

        private EntityManager entityManager;

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

        protected Object getTargetRepository(RepositoryMetadata metadata) {
            return new CustomQueryDslJpaRepositoryImpl<>(getEntityInformation(metadata.getDomainType()), entityManager);
        }

        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return CustomQueryDslJpaRepository.class;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

第4步:使用自定义存储库工厂

使用注释

@EnableJpaRepositories(repositoryFactoryBeanClass=CustomQueryDslJpaRepositoryFactoryBean.class)
Run Code Online (Sandbox Code Playgroud)

或者使用XML

<repositories base-package="com.acme.repository"  factory-class="com.acme.CustomQueryDslJpaRepositoryFactoryBean" />
Run Code Online (Sandbox Code Playgroud)

注意:不要将自定义存储库接口和实现放在与base-package相同的目录中.如果你正在放置然后将它们从扫描中排除,否则spring将尝试为它们创建bean

样品用法

public interface UserDemoRepository extends CustomQueryDslJpaRepository<UserDemo, Long>{
}

public class UserDemoService {
    @Inject 
    UserDemoRepository userDemoRepository;

    public Page<User> findAll(UserSearchCriteria userSearchCriteria, Pageable pageable) {
        QUserDemo user = QUserDemo.userDemo;
        return userDemoRepository.findAll(Projections.bean(UserDemo.class, user.id, user.username), UserPredicate.defaultUserSearch(userSearchCriteria), pageable);
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 好的,经过一番尝试,我能够解决问题.我注意到你需要使用[this answer](http://stackoverflow.com/a/21630123/1969096)中提到的`@NoRepositoryBean`来注释自定义界面,这也引用了这篇文章:).感谢您的帖子@Murali.很有帮助. (3认同)

Nea*_*leU 6

对于更新版本的Spring Data,我无法在没有遇到问题的情况下获得可接受的工作答案,但发现从Spring Data文档开始沿着这条路走下去,确实可以通过修改如下答案:

1.存储库界面

@NoRepositoryBean
public interface QueryDslPredicateAndProjectionExecutor<T, ID extends Serializable>
        extends JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {

    <PROJ> Page<PROJ> customFindWithProjection(FactoryExpression<PROJ> factoryExpression, Predicate predicate, Pageable pageable);
}
Run Code Online (Sandbox Code Playgroud)

2.存储库实现

public class QueryDslJpaEnhancedRepositoryImpl<T, ID extends Serializable> extends QueryDslJpaRepository<T, ID>
        implements QueryDslPredicateAndProjectionExecutor<T, ID> {

    //All instance variables are available in super, but they are private
    private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;

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

    public QueryDslJpaEnhancedRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
        this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
    }

    public QueryDslJpaEnhancedRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager,
                                 EntityPathResolver resolver) {

        super(entityInformation, entityManager, resolver);
        this.path = resolver.createPath(entityInformation.getJavaType());
        this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
        this.querydsl = new Querydsl(entityManager, builder);
    }

    @Override
    public <PROJ> Page<PROJ> customFindWithProjection(FactoryExpression<PROJ> factoryExpression, Predicate predicate, Pageable pageable) {
        JPQLQuery countQuery = createQuery(predicate);
        JPQLQuery query = querydsl.applyPagination(pageable, createQuery(predicate));

        Long total = countQuery.count();
        List<PROJ> content = total > pageable.getOffset() ? query.list(factoryExpression) : Collections.<PROJ>emptyList();

        return new PageImpl<PROJ>(content, pageable, total);
    }
}
Run Code Online (Sandbox Code Playgroud)

3.设置默认存储库实现

@EnableJpaRepositories(
    repositoryBaseClass=QueryDslJpaEnhancedRepositoryImpl.class,
    basePackageClasses=SomeRepository.class)
Run Code Online (Sandbox Code Playgroud)


Flo*_*dea 5

对于当前版本的Spring Data(1.11.1)和QueryDSL(4),您必须更改customFindWithProjection方法实现,如下所示:

@Override
public <PROJ> Page<PROJ> customFindWithProjection(FactoryExpression<PROJ> factoryExpression, Predicate predicate, Pageable pageable) {

    final JPQLQuery<?> countQuery = createCountQuery(predicate);
    JPQLQuery<PROJ> query = querydsl.applyPagination(pageable, createQuery(predicate).select(factoryExpression));

    long total = countQuery.fetchCount();
    List<PROJ> content = pageable == null || total > pageable.getOffset() ? query.fetch() : Collections.<PROJ> emptyList();

    return new PageImpl<PROJ>(content, pageable, total);
}
Run Code Online (Sandbox Code Playgroud)

其余代码保持不变.


归档时间:

查看次数:

25631 次

最近记录:

6 年,1 月 前