Skip to main content
 首页 » 编程设计

jpa之Spring Data JPA 和 Querydsl 使用 bean/构造函数投影获取列的子集

2024年11月01日17xxx_UU

我有一个实体类如下:

@Entity 
public class UserDemo implements Serializable { 
 
    @Id 
    private Long id; 
 
    private String username; 
 
    private String createdBy; 
    @Version 
    private int version; 
 
    /*** 
     * 
     * Getters and setters 
     */ 
} 

使用 Spring Data JPA 和 Querydsl 如何仅使用 id 获取 UserDemo 页面和 username属性填充?我需要使用分页和搜索。简而言之,我想达到与

Page<UserDemo> findAll(Predicate predicate, Pageable pageable); 

但是填充了有限的 UserDemo 字段。

请您参考如下方法:

看起来自定义存储库实现是现在要走的路,直到在 spring 数据中提供类似的东西。

我经历过http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.custom-implementations

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

第 1 步:共享行为的中间接口(interface)

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

第二步:实现中间接口(interface)
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); 
    } 
} 

第 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; 
        } 
    } 
} 

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

使用注释
@EnableJpaRepositories(repositoryFactoryBeanClass=CustomQueryDslJpaRepositoryFactoryBean.class) 

或使用 XML
<repositories base-package="com.acme.repository"  factory-class="com.acme.CustomQueryDslJpaRepositoryFactoryBean" /> 

注意:不要将自定义存储库接口(interface)和实现放在与 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); 
    } 
 
}