Spring 存储库方法中的数据过滤
Spring Data Filtering in Repositories methods
在我的 Spring Boot/Data/JPA 2.1 应用程序中,我有以下实体:
@Entity
@NamedEntityGraph(name = "graph.CardCategoryLevel", attributeNodes = { @NamedAttributeNode("cardCategory"), @NamedAttributeNode("level") })
@Table(name = "card_categories_levels")
public class CardCategoryLevel extends BaseEntity implements Serializable {
@Id
@SequenceGenerator(name = "card_categories_levels_id_seq", sequenceName = "card_categories_levels_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.AUTO, generator = "card_categories_levels_id_seq")
private Long id;
@OneToOne
@JoinColumn(name = "card_category_id")
private CardCategory cardCategory;
@OneToOne
@JoinColumn(name = "level_id")
private Level level;
@Column(name = "card_drop_rate")
private Float cardDropRate;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "cardCategoryLevel")
private List<Card> cards = new ArrayList<Card>();
....
}
和Spring数据CardCategoryLevelRepository
:
@Repository
public interface CardCategoryLevelRepository extends JpaRepository<CardCategoryLevel, Long> {
@Override
@EntityGraph(value = "graph.CardCategoryLevel", type = EntityGraphType.FETCH)
Page<CardCategoryLevel> findAll(Pageable pageable);
}
基于CardCategoryLevelRepository.findAll(Pageable pageable)
我可以通过分页和排序检索所有CardCategoryLevel
。
现在我不知道如何将过滤应用到这种方法中。例如,我需要有可能通过 CardCategory
or/and 通过 Level
or/and 通过 cardDropRate
过滤 CardCategoryLevel
。如何将过滤功能注入 CardCategoryLevelRepository.findAll(Pageable pageable)
方法或可能是新的类似方法?
使用 QueryDSL 和实体图实现。现在我可以使用 QueryDSL 谓词应用过滤(另外,请为这个 BUG 投票:https://jira.spring.io/browse/DATAJPA-684):
@Repository
public interface CardCategoryLevelRepository extends JpaRepository<CardCategoryLevel, Long>, QueryDslPredicateExecutor<CardCategoryLevel>, CardCategoryLevelRepositoryCustom {
@Override
@EntityGraph(value = "graph.CardCategoryLevel", type = EntityGraphType.LOAD)
List<CardCategoryLevel> findAll(Predicate predicate);
....
}
public interface CardCategoryLevelRepositoryCustom {
Page<CardCategoryLevel> findAll(Predicate predicate, Pageable pageable);
}
public class CardCategoryLevelRepositoryImpl extends SimpleJpaRepository<CardCategoryLevel, Long> implements CardCategoryLevelRepositoryCustom {
private final EntityManager entityManager;
private final EntityPath<CardCategoryLevel> path;
private final PathBuilder<CardCategoryLevel> builder;
private final Querydsl querydsl;
/**
* Workaround, must be removed once fixed
* https://jira.spring.io/browse/DATAJPA-684
*
*
* @param entityManager
*/
@Autowired
public CardCategoryLevelRepositoryImpl(EntityManager entityManager) {
super(CardCategoryLevel.class, entityManager);
this.entityManager = entityManager;
this.path = SimpleEntityPathResolver.INSTANCE.createPath(CardCategoryLevel.class);
this.builder = new PathBuilder<>(path.getType(), path.getMetadata());
this.querydsl = new Querydsl(entityManager, builder);
}
/**
* Workaround, must be removed once fixed
* https://jira.spring.io/browse/DATAJPA-684
*
*/
@Override
public Page<CardCategoryLevel> findAll(Predicate predicate, Pageable pageable) {
JPAQuery countQuery = createQuery(predicate);
JPAQuery query = (JPAQuery) querydsl.applyPagination(pageable, createQuery(predicate));
query.setHint(EntityGraph.EntityGraphType.LOAD.getKey(), entityManager.getEntityGraph("graph.CardCategoryLevel"));
Long total = countQuery.count();
List<CardCategoryLevel> content = total > pageable.getOffset() ? query.list(path) : Collections.<CardCategoryLevel> emptyList();
return new PageImpl<>(content, pageable, total);
}
private JPAQuery createQuery(Predicate predicate) {
return querydsl.createQuery(path).where(predicate);
}
}
在我的 Spring Boot/Data/JPA 2.1 应用程序中,我有以下实体:
@Entity
@NamedEntityGraph(name = "graph.CardCategoryLevel", attributeNodes = { @NamedAttributeNode("cardCategory"), @NamedAttributeNode("level") })
@Table(name = "card_categories_levels")
public class CardCategoryLevel extends BaseEntity implements Serializable {
@Id
@SequenceGenerator(name = "card_categories_levels_id_seq", sequenceName = "card_categories_levels_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.AUTO, generator = "card_categories_levels_id_seq")
private Long id;
@OneToOne
@JoinColumn(name = "card_category_id")
private CardCategory cardCategory;
@OneToOne
@JoinColumn(name = "level_id")
private Level level;
@Column(name = "card_drop_rate")
private Float cardDropRate;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "cardCategoryLevel")
private List<Card> cards = new ArrayList<Card>();
....
}
和Spring数据CardCategoryLevelRepository
:
@Repository
public interface CardCategoryLevelRepository extends JpaRepository<CardCategoryLevel, Long> {
@Override
@EntityGraph(value = "graph.CardCategoryLevel", type = EntityGraphType.FETCH)
Page<CardCategoryLevel> findAll(Pageable pageable);
}
基于CardCategoryLevelRepository.findAll(Pageable pageable)
我可以通过分页和排序检索所有CardCategoryLevel
。
现在我不知道如何将过滤应用到这种方法中。例如,我需要有可能通过 CardCategory
or/and 通过 Level
or/and 通过 cardDropRate
过滤 CardCategoryLevel
。如何将过滤功能注入 CardCategoryLevelRepository.findAll(Pageable pageable)
方法或可能是新的类似方法?
使用 QueryDSL 和实体图实现。现在我可以使用 QueryDSL 谓词应用过滤(另外,请为这个 BUG 投票:https://jira.spring.io/browse/DATAJPA-684):
@Repository
public interface CardCategoryLevelRepository extends JpaRepository<CardCategoryLevel, Long>, QueryDslPredicateExecutor<CardCategoryLevel>, CardCategoryLevelRepositoryCustom {
@Override
@EntityGraph(value = "graph.CardCategoryLevel", type = EntityGraphType.LOAD)
List<CardCategoryLevel> findAll(Predicate predicate);
....
}
public interface CardCategoryLevelRepositoryCustom {
Page<CardCategoryLevel> findAll(Predicate predicate, Pageable pageable);
}
public class CardCategoryLevelRepositoryImpl extends SimpleJpaRepository<CardCategoryLevel, Long> implements CardCategoryLevelRepositoryCustom {
private final EntityManager entityManager;
private final EntityPath<CardCategoryLevel> path;
private final PathBuilder<CardCategoryLevel> builder;
private final Querydsl querydsl;
/**
* Workaround, must be removed once fixed
* https://jira.spring.io/browse/DATAJPA-684
*
*
* @param entityManager
*/
@Autowired
public CardCategoryLevelRepositoryImpl(EntityManager entityManager) {
super(CardCategoryLevel.class, entityManager);
this.entityManager = entityManager;
this.path = SimpleEntityPathResolver.INSTANCE.createPath(CardCategoryLevel.class);
this.builder = new PathBuilder<>(path.getType(), path.getMetadata());
this.querydsl = new Querydsl(entityManager, builder);
}
/**
* Workaround, must be removed once fixed
* https://jira.spring.io/browse/DATAJPA-684
*
*/
@Override
public Page<CardCategoryLevel> findAll(Predicate predicate, Pageable pageable) {
JPAQuery countQuery = createQuery(predicate);
JPAQuery query = (JPAQuery) querydsl.applyPagination(pageable, createQuery(predicate));
query.setHint(EntityGraph.EntityGraphType.LOAD.getKey(), entityManager.getEntityGraph("graph.CardCategoryLevel"));
Long total = countQuery.count();
List<CardCategoryLevel> content = total > pageable.getOffset() ? query.list(path) : Collections.<CardCategoryLevel> emptyList();
return new PageImpl<>(content, pageable, total);
}
private JPAQuery createQuery(Predicate predicate) {
return querydsl.createQuery(path).where(predicate);
}
}