在具有许多属性的 Spring Data JPA 中过滤结果的最佳解决方案是什么?

aze*_*ati 3 hibernate jpa repository querydsl spring-data-jpa

我这里有一个产品表的案例,需要通过用户输入进行过滤,例如类别、颜色、尺寸、价格范围等等。

我正在使用 Spring Data JPA 并对其从方法名称派生的查询感到满意,当我被迫使用 @query 选项进行更复杂的查询时,例如连接和...

但是对于我需要的Filter方法,恐怕得写成这样了

public interface ProductRepository extends JpaRepository<Product, Long> {
   //..... other methods

Page<Product> findByCategoriesContainingAndSalepriceBetween(List<Category> categories, Float minprice, Float maxprice, PageRequest pagerequest);

Page<Product> findByCategoriesContaining(List<Category> categories, PageRequest pagerequest);

Page<Product> findByCategoriesContainingAndSizeIn(List<Category> categories,Int[] sizes, PageRequest pagerequest);

Page<Product> findByCategoriesContainingAndSizeInAndSalepriceBetween(List<Category> categories,Float minprice, Float maxprice, PageRequest pagerequest);
Run Code Online (Sandbox Code Playgroud)

}

似乎添加一些其他字段会迫使我写出这么多不同的组合

所以我查看了 QueryDsl 和 Specification 但它们似乎有很多额外的代码,你能把我放在正确的道路上吗?

Ala*_*Hay 5

我不同意 QueryDSL 导致大量额外代码。这是我用于 QueryDSL 的一些测试代码:

存储库定义:

public interface UserRepository extends PagingAndSortingRepository<User, Long>, QueryDslPredicateExecutor<User> {

    public User findOne(Predicate predicate);

    public List<User> findAll(Predicate predicate);
}
Run Code Online (Sandbox Code Playgroud)

基于各种属性及其组合的测试代码:

 @Test
    public void testFindByEmailAddress() {
        User user = repository.findOne(QUser.user.emailAddress.eq("jack@hamilton.net"));
        Assert.assertNotNull(user);
        Assert.assertEquals("Jack", user.getForename());
        Assert.assertEquals("Hamilton", user.getSurname());
    }

    @Test
    public void testFindByGender() {
        List<User> users = repository.findAll(QUser.user.gender.eq(Gender.M));
        Assert.assertEquals(4, users.size());

        users = repository.findAll(QUser.user.gender.eq(Gender.F));
        Assert.assertEquals(2, users.size());
    }

    @Test
    public void testFindByCity() {

        List<User> users = repository.findAll(QUser.user.address.town.eq("Edinburgh"));
        Assert.assertEquals(2, users.size());

        users = repository.findAll(QUser.user.address.town.eq("Stirling"));
        Assert.assertEquals(1, users.size());
    }

    @Test
    public void testFindByGenderAndCity() {
        List<User> users = repository.findAll(QUser.user.address.town.eq("Glasgow").and(QUser.user.gender.eq(Gender.M)));
        Assert.assertEquals(2, users.size());

        users = repository.findAll(QUser.user.address.town.eq("Glasgow").and(QUser.user.gender.eq(Gender.F)));
        Assert.assertEquals(1, users.size());
    }
Run Code Online (Sandbox Code Playgroud)