我有如下一個實體類以獲取列的子集UserDemo只有id
和username
屬性填充?我需要使用分頁以及搜索。總之我想實現同樣的結果春數據JPA和Querydsl用豆/構造投影
Page<UserDemo> findAll(Predicate predicate, Pageable pageable);
但UserDemo填充的有限的領域。
我有如下一個實體類以獲取列的子集UserDemo只有id
和username
屬性填充?我需要使用分頁以及搜索。總之我想實現同樣的結果春數據JPA和Querydsl用豆/構造投影
Page<UserDemo> findAll(Predicate predicate, Pageable pageable);
但UserDemo填充的有限的領域。
看起來像自定義存儲庫實現是現在的方式,直到類似的東西在春季數據可用。
了這是我實現它的工作原理。然而這將是很好直接在彈簧數據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);
}
步驟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);
}
}
第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" />
注意:不要將自定義庫界面並在同一個di中執行作爲基礎包的教區。如果要放置然後從掃描中排除,否則春天會盡量爲他們創造豆
使用範例
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);
}
}
對於較新版本的春天的數據,我不能讓接受的答案沒有擊中問題需要解決,但發現下去從Spring數據文件的路徑,通過修改這個問題的答案如下做工作:
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);
}
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);
}
}
3.設置默認存儲庫實現
@EnableJpaRepositories(
repositoryBaseClass=QueryDslJpaEnhancedRepositoryImpl.class,
basePackageClasses=SomeRepository.class)
春天數據的當前版本(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);
}
代碼的其餘部分保持不變。
什麼是FactoryExpression是自定義類還是預定義的? –
FactoryExpression是Querydsl中Projections的基類。 http://www.querydsl.com/static/querydsl/3.2.0/apidocs/com/mysema/query/types/FactoryExpression.html – Murali
我得到一個'引起:org.springframework.data.mapping.PropertyReferenceException:No找到類型'的財產找到時,我嘗試了這一點。這是爲什麼? 當然代表我的實體類型。 –