Spring JPA Repository自定义查询

时间:2017-06-13 18:20:33

标签: spring-boot spring-data spring-data-jpa

此自定义查询有效(这只是用于说明问题的基本查询):

public interface BookQueryRepositoryExample extends Repository<Book, Long> {
    @Query(value = "select * from Book b where b.name=?1", nativeQuery = true)
    List<Book> findByName(String name);
}

但是我需要另一个自定义查询,其中where子句将在调用方法之前动态构造。

public interface BookQueryRepositoryExample extends Repository<Book, Long> {
    @Query(value = "select * from Book b where ?1", nativeQuery = true)
    List<Book> findByWhatever(String qry);
}

但我无法使其发挥作用。有没有解决方法?

更新时间:6/16/2017

只是想提一下,我正在搜索的字段是'非规范化'形式。值可能如下所示(如下)。所以我的查询有一系列类似的陈述

样本1:

name:John Smith;address1:123 Xyz St;city:New York;zip:12345;country:USA;id:ABC1234;email:js@abc.com;

示例2:重新排列

address1:123 Xyz St;zip:12345;email:js@abc.com;name:John Smith;country:USA;id:ABC1234;city:New York;

示例3:缺少字符串/文本

zip:12345;email:js@abc.com;name:John Smith;id:ABC1234;city:New York;

5 个答案:

答案 0 :(得分:1)

这不会起作用,至少不是这种方法。

查询中的占位符不会被某些任意String替换,而是变量,只能代替您提供的文字作为文字。

但是作为@M。 Deinum指出有其他选择:你可以write a custom method并使用

  • JPA Criteria API
  • JPQL
  • 规格
  • QueryDSL

有关示例,请参阅此文章:https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

答案 1 :(得分:1)

解决这个问题就像是,您可以通过注入EnitiyManager来创建一个类来执行动态查询,如下所示:

//Pseudo code
@Repository
public class SomeDao {

    @PersistenceContext
    private EntityManager entityManager;

    public List<Book> findByWhatever(String qry){
        Query q = entityManager.createNativeQuery(qry);
        List<Object[]> books = q.getResultList();
        //......  Your logic goes here
        //return ...
    }
}

答案 2 :(得分:1)

例如如果要根据authorName,title和cost等属性的组合查找Book,则可以使用以下查询

public interface BookQueryRepositoryExample extends Repository<Book, Long> { @Query(value = "select * from Book b where (?1 or null) and (?2 or null) and (?3 or null) ", nativeQuery = true ) List<Book> findByWhatever(String authorName,String title,Double cost); }

答案 3 :(得分:1)

您可以使用spring-data提供的规范界面创建动态where子句。

以下是您的链接:https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

答案 4 :(得分:0)

  

@Query(value =&#34; select * from Book b where?1&#34;,nativeQuery = true)   列出findByWhatever(String qry);

首先,建议不要使用您的方法,并且最有可能导致 SQL注入漏洞(如果您没有以正确的方式处理&#39; qry&#39;参数)。< / p>

其次,您正在尝试重新发明轮子。有很多可能的方法来实现动态查询,正如@Jens Schauder在他的回答中已经提到的那样。如果你不需要复杂的东西,我会添加一个似乎最简单的方法。它被称为&#34; Query by Example&#34;。

public interface BookRepository extends JpaRepository<Book, Long>{
}

然后,您创建一个对象的实例,该实例看起来就像您要查找的对象一样,这意味着您必须设置用于动态查询生成的属性:

Book book = new Book();
book.setYear(2015);
book.setPublisher("O'Realy")

Example<Book> bookExample = Example.of(book);

最后一步是将您的示例对象传递给Spring Data JPA存储库:

List<Book> books = bookRepository.findAll(bookExample);

因此,您将获得O&#39; Realy在2015年发布的图书清单。关于它的好处是你可以通过在book实例中设置它来添加更多字段以便在运行时搜索。

如果您需要比精确值匹配更复杂的东西,您可以使用匹配器。在下面的示例中,Spring Data JPA将搜索名称以&#34; O&#34;开头的所有书籍。无视案例。

Book book = new Book();
book.setName("O")

ExampleMatcher matcher = ExampleMatcher.matching().
    .withMatcher("publisher", startsWith().ignoreCase());

Example<Book> bookExample = Example.of(book, matcher);

List<Book> books = bookRepository.findAll(bookExample);