Jpa 2.0 JPA 2:将@NamedNativeRequesty更改为CriteriaBuilder等效项

Jpa 2.0 JPA 2:将@NamedNativeRequesty更改为CriteriaBuilder等效项,jpa-2.0,Jpa 2.0,是否可以更改此@NamedQuery查询: SELECT @rownum:=@rownum+1 'no', m.title, m.author, REPLACE(SUBSTRING_INDEX(m.content, ' ', 20), '<br>', ' '), m.viewed, m.hashid FROM book m, (SELECT @rownum:=0) r WHERE m.lang = ?1 AND m.title like CONCAT('%',?2,'%') ORDE

是否可以更改此@NamedQuery查询:

SELECT @rownum:=@rownum+1 'no', m.title, m.author, REPLACE(SUBSTRING_INDEX(m.content, ' ', 20), '<br>', ' '), m.viewed, m.hashid FROM book m, (SELECT @rownum:=0) r WHERE m.lang = ?1 AND m.title like CONCAT('%',?2,'%') ORDER BY m.title asc

与标准构建器等效。是不是?…

我认为这样做的自然方式是用JPA处理查询,而用Java处理编号和字符串混乱。查询如下所示:

EntityManagerFactory emf;
String lang;
String keyword;

CriteriaBuilder builder = emf.getCriteriaBuilder();
final CriteriaQuery<Book> criteria = builder.createQuery(Book.class);
Root<Book> root = criteria.from(Book.class);
criteria.where(builder.and(builder.equal(root.get(Book_.lang), lang), builder.like(root.get(Book_.title), ("%" + keyword + "%"))));
criteria.orderBy(builder.asc(root.get(Book_.title)));
由于结果以列表的形式返回,您可以简单地使用“no”字段的列表索引,并且可以在Book上编写getContentSnippet方法来执行子字符串和替换

如果您真的想在数据库中处理字符串,也许是为了减少传输的文本量,那么您可以编写一个元组查询,它可以检索书籍和片段。请注意,我仍然会检索整本书,而不是单个字段,因为这使后续编程更加容易;如果要避免传输整个内容,请在Book类中将其标记为延迟加载。查询如下所示:

CriteriaBuilder builder = emf.getCriteriaBuilder();
final CriteriaQuery<Tuple> criteria = builder.createTupleQuery();
final Root<Book> root = criteria.from(Book.class);
final Expression<String> snippetExpr = builder.substring(root.get(Book_.content), 1, 120);
criteria.multiselect(root, snippetExpr);
criteria.where(builder.and(builder.equal(root.get(Book_.lang), lang), builder.like(root.get(Book_.title), ("%" + keyword + "%"))));
criteria.orderBy(builder.asc(root.get(Book_.title)));
我使用substring来构建代码段,因为我使用的是PostgreSQL,它没有substring\u INDEX函数的等价物。您可以使用CriteriaBuilder.function使用MySQL调用它。我仍然没有在查询中进行编号或替换,因为我仍然认为在代码中这样做更好

EntityManager em = emf.createEntityManager();
TypedQuery<Tuple> q = em.createQuery(criteria);
List<Tuple> booksAndSnippets = q.getResultList();
for (int i = 0; i < booksAndSnippets.size(); ++i) {
    Tuple bookAndSnippet = booksAndSnippets.get(i);
    int no = i + 1;
    Book book = bookAndSnippet.get(root);
    String snippet = bookAndSnippet.get(snippetExpr).replace("<br>", " ");
}

不过,我真的认为您可能会更容易使用JPQL

是的,在尝试了很多不同的方法之后,包括CriteriaBuilder,JPQL是迄今为止对我来说最简单的方法。如果Primefaces有一种对返回结果集进行编号的方法,那么我不需要这个@rownum:=@rownum+1。唉,我现在只能坚持使用JPQL,希望JSF、JPA和Primefaces的未来版本能够提供更好的定制显示信息的方法。啊哈,这就是为什么你在查询中要做这么多逻辑:你要受一些愚蠢的UI库的摆布。也许值得将此重新发布为Primefaces/JSF问题,关于如何在列表上为迭代添加编号。谢谢,Tom。我会尝试最后一件事,如果这不起作用,我会把上面的问题重新发布。