[英]JPA/MySQL - Whats wrong with this JPQL query?
我有實體Post
:
@Entity
@Table(name = "post")
@NamedQueries({
@NamedQuery(name = "getNewestPosts", query = "SELECT p FROM Post p ORDER BY p.date DESC"), // getting resultList ordered by date
@NamedQuery(name = "getMostVisitedPosts", query = "SELECT p FROM Post p ORDER BY p.visitors DESC"), // ordered by most visited
@NamedQuery(name = "getMostCommentedPosts", query = "SELECT p FROM Post p ORDER BY SIZE(p.comments) DESC")
})
public class Post implements Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "post_id", unique = true, nullable = false)
private Integer id;
@Column(name = "post_title", length=300, unique = false, nullable = false)
private String title;
@Column(name = "post_date", unique = false, nullable = false)
private Date date;
@Column(name = "post_summary", length=1000, unique = false, nullable = true)
private String summary;
@Column(name = "post_content", length=50000, unique = false, nullable = false)
private String content;
@Column(name = "post_visitors", unique = false, nullable = false)
private Integer visitors;
@ManyToOne
@JoinColumn (name = "user_id", referencedColumnName="user_id", nullable = false)
private User user;
@ManyToOne
@JoinColumn (name = "category_id", referencedColumnName="category_id", nullable = false)
private Category category;
@OneToMany(cascade = { ALL }, fetch = EAGER, mappedBy = "post")
private Set<Comment> comments = new HashSet<Comment>();
...
實體Comment
:
@Entity
@Table(name = "comment")
public class Comment implements Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "comment_id", unique = true, nullable = false)
private Integer id;
@Column(name = "comment_title", length=300, unique = false, nullable = false)
private String title;
@Column(name = "comment_date", unique = false, nullable = false)
private Date date;
@Column(name = "comment_content", length=600, unique = false, nullable = false)
private String content;
@ManyToOne
@JoinColumn (name = "user_id", referencedColumnName="user_id", nullable = false)
private User user;
@ManyToOne
@JoinColumn (name = "post_id", referencedColumnName="post_id", nullable = false)
private Post post;
...
然后,在PostDAOBean
有以下方法:
public List<Post> getMostCommentedPosts(int page, int postsPerPage){
Query q = em.createNamedQuery("getMostCommentedPosts");
q.setFirstResult(page - 1);
q.setMaxResults(postsPerPage);
List<Post> resultList = (List<Post>) q.getResultList();
if (resultList.isEmpty())
return null;
else
return resultList;
}
當我在servlet中調用此方法時,我得到下一個異常:
[07.01.2014 09:06] Class name: class mbs2.blog.server.session.PostDAOBean, method name: public java.util.List mbs2.blog.server.session.PostDAOBean.getMostCommentedPosts(int,int) started
[07.01.2014 09:06] Class name: class mbs2.blog.server.session.PostDAOBean, method name: public java.util.List mbs2.blog.server.session.PostDAOBean.getMostCommentedPosts(int,int)<openjpa-2.2.0-r422266:1244990 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: "Encountered "SIZE" at character 31, but expected: ["AVG", "COUNT", "KEY", "MAX", "MIN", "SUM", "VALUE", <IDENTIFIER>]." while parsing JPQL "SELECT p FROM Post p ORDER BY SIZE(p.comments) DESC". See nested stack trace for original parse error.
at org.apache.openjpa.kernel.jpql.JPQLParser.parse(JPQLParser.java:51)
at org.apache.openjpa.kernel.ExpressionStoreQuery.newCompilation(ExpressionStoreQuery.java:154)
at org.apache.openjpa.kernel.QueryImpl.newCompilation(QueryImpl.java:672)
at org.apache.openjpa.kernel.QueryImpl.compilationFromCache(QueryImpl.java:654)
at org.apache.openjpa.kernel.QueryImpl.compileForCompilation(QueryImpl.java:620)
at org.apache.openjpa.kernel.QueryImpl.compileForExecutor(QueryImpl.java:682)
at org.apache.openjpa.kernel.QueryImpl.compile(QueryImpl.java:589)
at org.apache.openjpa.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:1038)
at org.apache.openjpa.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:102)
at org.apache.openejb.persistence.JtaEntityManager.createNamedQuery(JtaEntityManager.java:274)
at mbs2.blog.server.session.PostDAOBean.getMostCommentedPosts(PostDAOBean.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
您可以看到命名查詢是: SELECT p FROM Post p ORDER BY SIZE(p.comments) DESC
。
異常的原因是什么?
編輯好了,我看到函數SIZE(p.comments)
不能在JPQL中用它來訂購。
使用JPQL獲取相同數據的另一種方法是什么? 適當的JPQL查詢?
編輯嘗試使用JPA Criteria API實現此查詢:
public List<Post> getMostCommentedPosts(int page, int postsPerPage){
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Post> cq = cb.createQuery(Post.class);
Root<Post> p = cq.from(Post.class);
cq.select(p);
cq.orderBy(cb.desc(???));
...???...
}
需要幫助JPA Criteria API。
好吧,編譯器咆哮:“遇到”SIZE“在31號,但預期:[”AVG“,”COUNT“,”KEY“,”MAX“,”MIN“,”SUM“,”VALUE“,]。” 解析JPQL時....“
SIZE是一個不符合ORDER BY子句規范的函數:
ORDER BY子句允許對查詢返回的對象或值進行排序。 ORDER BY子句的語法是orderby_clause :: = ORDER BY orderby_item {,orderby_item} * orderby_item :: = state_field_path_expression [ASC | DESC]使用MAX或MIN指定DISTINCT是合法的,但它不會影響結果。 當在查詢中使用ORDER BY子句時,查詢的SELECT子句的每個元素必須是以下之一:標識變量x,可選地表示為OBJECT(x),single_valued_association_path_expression或state_field_path_expression。
此外:
SIZE函數返回一個整數值,即集合的元素數。 如果集合為空,則SIZE函數的計算結果為零。
嘗試這個:
public List<Post> getMostCommentedPosts(int page, int postsPerPage){
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Post> cq = cb.createQuery(Post.class);
Root<Post> p = cq.from(Post.class);
cq.select(p).where(cb.isNotEmpty(p.get("comments")));
List list = em.createQuery(cq).getResultList();
for(Set each : list)
{
System.out.println(each.size());
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.