JPA 2:将@NamedNativeQuery更改为CriteriaBuilder等效项

时间:2011-04-14 20:04:47

标签: 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,'%') ORDER BY m.title asc

到CriteriaBuilder的等价物。或者不是?...

1 个答案:

答案 0 :(得分:1)

我认为执行此操作的自然方法是在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_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了!