【问题标题】:Spring Data Rest: Query parameters chained with logical ORSpring Data Rest:使用逻辑 OR 链接的查询参数
【发布时间】:2017-12-06 15:46:50
【问题描述】:

我有一个由以下存储库公开的实体:

public interface InsertRepository extends PagingAndSortingRepository<InsertEntity, Long>, QueryDslPredicateExecutor<InsertEntity>, QueryDslBinderCustomizer<QInsertEntity> {
    @Override
    default void customize(QuerydslBindings bindings, QInsertEntity insert) {
        bindings.bind(String.class).all(StringPath path, Collection<? extends String> values) -> {
            BooleanBuilder predicate = new BooleanBuilder();
            values.forEach(value -> predicate.or(path.containsIgnoreCase(value)));

            return predicate;
        });
    }
}

我希望它做的是所有 GET 查询参数都链接为逻辑 OR,以便像 ?description=searchText&amp;customerName=searchText 这样的查询将执行如下所示的 SQL 查询:

WHERE description LIKE '%searchText%' OR customerName LIKE '%searchText%'

但是,我一定做错了什么,因为它不起作用 - 它将所有查询参数放入 AND 查询中。这将导致仅选择那些在 customerName AND 中包含 searchText 的记录。

【问题讨论】:

  • TypeBinder$all() 允许您自定义按路径或按类指定的多值绑定。但即使您“按类”自定义绑定,查询参数也不会被全局处理。例如
  • @MarcTarin 好的,如果我理解正确,我无法使用customize 方法完成我需要的工作,对吧?
  • 例如?description=searchText&amp;description=searchInt 会给你WHERE description LIKE '%searchText%' OR description LIKE '%searchInt%'customerName 的出现被作为一个单独的子句处理,所有子句都用 AND 连接。所以不,据我所知,您无法使用 customize 方法完成您需要的工作。
  • 好的,非常感谢 - 我想我会为此使用自定义查询。

标签: java spring spring-data-rest querydsl


【解决方案1】:

您可以使用命名参数,例如
示例 53. 使用命名参数

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation

public interface UserRepository extends JpaRepository<User, Long> {
   @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
   User findByLastnameOrFirstname(@Param("lastname") String lastname,
                               @Param("firstname") String firstname);
}

【讨论】:

  • 这将需要我创建一个新的控制器方法,该方法又会调用该方法。我正在尝试通过正常的 REST 接口公开该行为,因此我不需要为查询调用特定方法。
  • 框架会自动为你生成一个/search/findByLastnameOrFirstname端点。
  • 这有一些严重的问题...查看我的答案了解详情。
【解决方案2】:

@kafkas 提供的答案根本不准确。它的问题很少:

  1. 注解@Query 已过时 - Spring 会自动为您完成,您只需正确输入方法的名称即可。
  2. 注解 @Param 已过时 - Spring 自动按给定顺序获取参数,并与方法名称中的参数匹配。
  3. 您返回单个用户实体,但您仍然使用 findBy 而不是 findOne - 如果找到多个记录,这会导致错误。
  4. 最后但并非最不重要的 - 提供的方法不会使用LIKE 比较,而是使用等于。如果您希望启动 SQL 查询,您应该使用 findByXXXContaining,例如:... WHERE firstname LIKE "%name%"
  5. 使用 Spring,如果不需要,我建议不要使用 JpaRepository。最简单的实现是 CrudRepository,它涵盖了大多数用例。

总之,你的方法应该被简化,看起来像这样:

public interface UserRepository extends CrudRepository<User, Long> { User findOneByLastnameContainingOrFirstnameContaining(String lastname, String firstname); }

这应该会导致查询:

SELECT * FROM User u WHERE u.lastname LIKE '%lastname' OR u.firstname LIKE '%firstname%;'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多