2013-08-18 31 views
20

Tôi có một lớp thực thể như sau:mùa xuân dữ liệu JPA và Querydsl để lấy tập hợp con của các cột bằng đậu/constructor chiếu

@Entity 
public class UserDemo implements Serializable { 

    @Id 
    private Long id; 

    private String username; 

    private String createdBy; 
    @Version 
    private int version; 

    /*** 
    * 
    * Getters and setters 
    */ 
} 


Sử dụng mùa xuân dữ liệu JPA và Querydsl làm thế nào để tôi lấy một trang UserDemo chỉ với idusername thuộc tính được điền? Tôi cần sử dụng phân trang cũng như tìm kiếm. Nói tóm lại tôi muốn đạt được kết quả tương tự như

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

nhưng với lĩnh vực hạn chế về UserDemo dân cư.

Trả lời

28

Dường như triển khai kho lưu trữ tùy chỉnh là cách để thực hiện cho đến khi có điều gì đó tương tự có sẵn trong dữ liệu mùa xuân.

Tôi đã trải qua http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.custom-implementations

Đây là thực hiện của tôi mà làm việc. Tuy nhiên nó sẽ là tốt để có phương pháp này có sẵn trực tiếp trong mùa xuân-Data-JPA

Bước 1: Giao diện trung gian cho hành vi chia sẻ

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

Bước 2: Thực hiện giao diện trung gian

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

Bước 3: Tạo nhà máy kho lưu trữ tùy chỉnh để thay thế mặc định

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

Bước 4: Sử dụng các nhà máy kho tùy chỉnh

Sử dụng chú thích

@EnableJpaRepositories(repositoryFactoryBeanClass=CustomQueryDslJpaRepositoryFactoryBean.class) 

HOẶC sử dụng XML

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

Lưu ý: Không đặt giao diện tùy chỉnh kho và thực hiện trong cùng một di rectory như là gói cơ sở. Nếu bạn đang đặt sau đó loại trừ chúng khỏi quá trình quét khác mùa xuân sẽ cố gắng để tạo ra hạt cà phê cho họ

mẫu sử dụng

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

} 
+0

FactoryExpression là lớp tùy chỉnh hoặc được xác định trước. –

+0

FactoryExpression là lớp cơ sở cho các dự trong Querydsl. http://www.querydsl.com/static/querydsl/3.2.0/apidocs/com/mysema/query/types/FactoryExpression.html – Murali

+0

Tôi nhận được 'Nguyên nhân bởi: org.springframework.data.mapping.PropertyReferenceException: Không tìm thấy thuộc tính cho loại 'khi tôi thử. Tại sao vậy? tất nhiên là viết tắt của loại Thực thể của tôi. –

3

Để biết thêm các phiên bản gần đây của dữ liệu mùa xuân, tôi không thể có được câu trả lời được chấp nhận để làm việc mà không cần nhấn các vấn đề, nhưng thấy rằng đi xuống con đường từ các tài liệu dữ liệu mùa xuân, làm việc bằng cách sửa đổi câu trả lời như sau:

1. giao diện kho

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

2.Việc thực hiện kho

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

3. Thiết lập việc thực hiện kho lưu trữ mặc định

@EnableJpaRepositories(
    repositoryBaseClass=QueryDslJpaEnhancedRepositoryImpl.class, 
    basePackageClasses=SomeRepository.class) 
+0

bạn có cơ sở mã cho điều này ở đâu không, PROJ có nghĩa là giao diện chiếu của tôi không , tôi nhận được một số lỗi biên dịch, xin chia sẻ bất kỳ trang web github hoặc bất cứ nơi nào tôi có thể tham khảo ... – surya

+0

thực sự sau khi tôi thực hiện, mặc dù phần dsl công trình, kết quả tôi nhận được không chiếu nhưng toàn bộ đối tượng. vì vậy trở lại một hình vuông .. xin vui lòng cho tôi biết nếu bạn có mã mẫu ở đâu đó cho truy vấn dsl + chiếu – surya

+0

Và tôi đang sử dụng phiên bản khởi động mùa xuân 1.4.0.RELEASE – surya

1

Đối với các phiên bản hiện tại của dữ liệu Spring (1.11.1) và QueryDSL (4), bạn phải thay đổi triển khai phương thức customFindWithProjection như sau:

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

Phần còn lại của mã vẫn giữ nguyên.

Các vấn đề liên quan