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

Hibernate 在具有许多属性的Spring数据JPA中过滤结果的最佳解决方案是什么?,hibernate,jpa,repository,spring-data-jpa,querydsl,Hibernate,Jpa,Repository,Spring Data Jpa,Querydsl,我这里有一个products表的例子,它需要通过用户输入进行过滤,比如类别、颜色、大小、价格范围等等 我使用的是SpringDataJPA,很满意它从方法名派生的查询,当我被迫使用@query选项时,我只使用@query选项来进行更复杂的查询,比如连接和 但是对于我需要的Filter方法,恐怕我必须这样写 公共接口ProductRepository扩展了JpaRepository{ //……其他方法 PageFindByCategories包含和SalePriceBetween(列出类别、浮动最

我这里有一个products表的例子,它需要通过用户输入进行过滤,比如类别、颜色、大小、价格范围等等

我使用的是SpringDataJPA,很满意它从方法名派生的查询,当我被迫使用@query选项时,我只使用@query选项来进行更复杂的查询,比如连接和

但是对于我需要的Filter方法,恐怕我必须这样写

公共接口ProductRepository扩展了JpaRepository{
//……其他方法
PageFindByCategories包含和SalePriceBetween(列出类别、浮动最小价格、浮动最大价格、PageRequest PageRequest);
PageFindByCategories包含(列表类别、PageRequest PageRequest);
PageFindByCategoriesContainingAndSizeIn(列表类别、Int[]大小、PageRequest PageRequest);
PageFindByCategories包含AndSizeInAndSalePriceBetween(列表类别、浮动最小价格、浮动最大价格、页面请求页面请求);
}

似乎添加一些其他字段会迫使我编写这么多不同的组合
我看过QueryDsl和规范,但它们似乎有太多额外的代码,你能让我走上正确的道路吗?

我不同意QueryDsl会导致大量额外的代码。以下是我为QueryDSL编写的一些测试代码:

存储库定义:

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

    public User findOne(Predicate predicate);

    public List<User> findAll(Predicate predicate);
}
public interface UserRepository扩展了分页和排序存储库queryDSL谓词执行器{
公共用户findOne(谓词);
公共列表findAll(谓词);
}
基于各种属性及其组合的测试代码:

 @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());
    }
@测试
public void testFindByEmailAddress(){
User User=repository.findOne(QUser.User.emailAddress.eq(“jack@hamilton.net"));
Assert.assertNotNull(用户);
Assert.assertEquals(“Jack”,user.getForename());
Assert.assertEquals(“Hamilton”,user.getnam姓氏());
}
@试验
公共无效testFindByGender(){
List 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());
}
@试验
public void testFindByCity(){
List users=repository.findAll(QUser.user.address.town.eq(“爱丁堡”);
Assert.assertEquals(2,users.size());
users=repository.findAll(QUser.user.address.town.eq(“斯特林”);
Assert.assertEquals(1,users.size());
}
@试验
公共无效testFindByGenderAndCity(){
List users=repository.findAll(QUser.user.address.town.eq(“格拉斯哥”))和(QUser.user.gender.eq(gender.M));
Assert.assertEquals(2,users.size());
users=repository.findAll(QUser.user.address.town.eq(“格拉斯哥”))和(QUser.user.gender.eq(gender.F));
Assert.assertEquals(1,users.size());
}

我同意您的代码看起来很不错,但是像我的案例这样的一些组合呢?在代码中是否有类似的东西可以展示?示例中的testFindByGenderAndCity()?我可以使用“and”操作符传递任意数量的参数,而无需向存储库中添加任何代码。例如,您将如何以编写代码的方式在此处进行连接和/或分组结果?你不能用
在(…)、在(…)和(…)之间连接它们,你的回答让我尝试了QueryDsl,是的,这是一个很好的工具,它似乎解决了我的大多数问题,但你的回答仍然缺少关于如何对结果或更复杂的事情进行分组的要点,我知道querydsl的JPA实现只适用于querydsl的布尔表达式,我不能像这样做一个小组,对吗?一年后注意到我的问题后,我现在对querydsl上瘾了,并且用它做了很多很棒的事情。我刚坠入爱河,伙计们,试试看,你们就会明白我的意思了。
 @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());
    }