当前位置: 首页 > 知识库问答 >
问题:

Spring JPA存储库动态查询

柳胜
2023-03-14

目前我一直在使用以下Spring JPA存储库自定义查询,

 @Query("SELECT usr FROM User usr  WHERE usr.configurable = TRUE "
              + "AND (" +
                        "lower(usr.name) like lower(:filterText) OR lower(usr.userType.classType.displayName) like lower(:filterText) OR lower(usr.userType.model) like lower(:filterText)"
              +      ")"
              + "")
  public List<User> findByFilterText(@Param("filterText") String filterText, Sort sort);

我需要修改这个查询时,筛选文本将是逗号分隔的值。但按照以下方式,它将是一个动态查询,我如何执行它。

我需要构建动态查询,

String sql = "SELECT usr FROM User usr WHERE usr.configurable = TRUE";

for(String word : filterText.split(",")) {
                sql += " AND (lower(usr.name) like lower(:" + word + ") OR lower(usr.userType.classType.displayName) like lower(:" + word + ") OR lower(usr.userType.model) like lower(:" + word + "))";
}

共有1个答案

山疏珂
2023-03-14

根据JB Nizet和spring-data文档,您应该使用自定义接口+存储库实现。

使用以下方法创建接口:

public interface MyEntityRepositoryCustom {
    List<User> findByFilterText(Set<String> words);
}

创建实现:

@Repository
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
    @PersistenceContext
    private EntityManager entityManager;

    public List<User> findByFilterText(Set<String> words) {
        // implementation below
    }
}
public interface MyEntityRepository extends JpaRepository<MyEntity, Long>, MyEntityRepositoryCustom {
    // other query methods
}
dao.findByFilterText(new HashSet<String>(Arrays.asList(filterText.split(","))));

您要连接的必须是有效的JPQL标识符,即:后跟一个java标识符开始,也可以后跟某个java标识符部分。这意味着如果您的CSV包含foo bar,baz,您将尝试使用foo bar作为标识符,您将得到一个异常。

您可以使用criteriaBuilder以安全的方式构造查询:

public List<User> findByFilterText(Set<String> words) {
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<User> q = cb.createQuery(User.class);
    Root<User> user = q.from(User.class);

    Path<String> namePath = user.get("name");
    Path<String> userTypeClassTypeDisplayName = 
                     user.get("userType").get("classType").get("displayName");
    Path<String> userTypeModel = user.get("userType").get("model");
    List<Predicate> predicates = new ArrayList<>();
    for(String word : words) {
        Expression<String> wordLiteral = cb.literal(word);
        predicates.add(
                cb.or(
                    cb.like(cb.lower(namePath), cb.lower(wordLiteral)),
                    cb.like(cb.lower(userTypeClassTypeDisplayName),
                            cb.lower(wordLiteral)),
                    cb.like(cb.lower(userTypeModel), cb.lower(wordLiteral))
                )
        );
    }
    q.select(doc).where(
            cb.and(predicates.toArray(new Predicate[predicates.size()]))
    );

    return entityManager.createQuery(q).getResultList();
}
 类似资料:
  • 现在,我的CreditCard对象包含两个属性(发行商、network和id),因此很容易搜索像这样的对象: 但是,我不喜欢这段代码,因为我必须创建所有属性的组合,而且会非常混乱。在未来,我计划有15个财产,所以‘如果’链是不可能的。 我想问你,如何使用spring-data-redis创建动态查询,使Redis能够以比检查每个属性更好的方式基于对象属性返回交集?

  • ...除了这不存在。但这是关于我在这里想做什么。 或相反的: ...它获取每个GameCharacter的最早版本。为此,我已经尝试了,但显然Javers没有从最后开始计算版本。 这方面的Gradle依赖关系是:

  • 问题内容: 我在存储过程中创建一个动态查询。我的存储过程如下: 当我尝试通过以下调用运行它时: 我收到以下错误消息: 错误代码:1054。“ where子句”中的未知列“ SPA” 我在没有where条件的情况下进行了测试,并且工作正常,但是在where条件不起作用的情况下,我尝试使用@和变量名一起使用,但仍然无法正常工作。 谢谢你的帮助。 问题答案: 您错过了条款中的引号。 尝试这样: 说明 :

  • 问题内容: 我正在使用,要求提供具有不同字段的搜索功能。搜索之前输入的字段是optional.I有5场说。 在这里我只需要查询用户给定的值,其他字段应该被忽略。 因此,这里我们考虑输入的值和进行查询。在这种情况下,Spring数据是具有限制中提到的这篇文章(不可扩展,所有可能出现的问题,应书面)我使用的,但仍然存在问题的领域应该被忽视,需要开发的几乎所有可能出现的问题。在这。如果搜索字段是? 用可

  • 如何使用@ Query(value = " SELECT * FROM do _ not _ track WHERE(user _ id = 7)AND(' 2022-06-25 ' BETWEEN FROM _ date AND to _ date)OR(' 2022-06-30 ' BETWEEN FROM _ date AND to _ date)",nativeQuery = true)在

  • 问题内容: 我正在使用,要求提供具有不同字段的搜索功能。搜索之前输入的字段是有5场说。 在这里我只需要查询用户给定的值,其他字段应该被忽略。 因此,这里我们考虑输入的值和进行查询。在这种情况下,Spring数据是具有限制中提到的这篇文章(不可扩展,所有可能出现的问题,应书面)我使用的,但仍然存在问题的null领域应该被忽视,需要开发的几乎所有可能出现的问题。在这。如果搜索字段是? 用可选字段实现搜