Spring Data Rest:查询以逻辑OR链接的参数

时间:2017-07-03 11:32:06

标签: java spring spring-data-rest querydsl

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

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&customerName=searchText这样的查询执行如下的SQL查询:

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

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

2 个答案:

答案 0 :(得分:1)

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

  1. 注释@Query是obsolette - Spring会自动为您执行此操作,您只需要正确键入方法的名称。
  2. 注释@Param是obsolette - Spring按给定顺序自动获取参数,与方法名称中的参数匹配。
  3. 您返回单个用户实体,但仍然使用findBy而不是findOne - 如果找到多条记录,则会导致错误。
  4. 最后但并非最不重要的 - 提供的方法不会使用LIKE比较,而是等于。如果您希望启动SQL查询,请使用findByXXXContaining,如:... WHERE firstname LIKE "%name%"
  5. 使用Spring,如果您不需要,我建议不要使用JpaRepository。最简单的实现是CrudRepository,它涵盖了大多数用例。
  6. 总之,您的方法应该简化并看起来像这样:

    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%;'

答案 1 :(得分:0)

您可以使用命名参数,例如
示例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);
}