简体   繁体   English

JPA / MySQL - 这个JPQL查询有什么问题?

[英]JPA/MySQL - Whats wrong with this JPQL query?

I have entity Post : 我有实体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>();
...

Entity 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;
...

Then, in the PostDAOBean is following method: 然后,在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;
}

When I call this method in servlet I get next exception: 当我在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)
...

You can see that named query is: SELECT p FROM Post p ORDER BY SIZE(p.comments) DESC . 您可以看到命名查询是: SELECT p FROM Post p ORDER BY SIZE(p.comments) DESC

What is the cause of exception? 异常的原因是什么?

EDIT OK, I see that function SIZE(p.comments) can not be used in JPQL to be ordered by it. 编辑好了,我看到函数SIZE(p.comments)不能在JPQL中用它来订购。

What is the alternative way of getting same data with JPQL? 使用JPQL获取相同数据的另一种方法是什么? Proper JPQL query? 适当的JPQL查询?

EDIT Trying to implement this query with JPA Criteria API: 编辑尝试使用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(???));
                ...???...
}

Need help with JPA Criteria API. 需要帮助JPA Criteria API。

Well, compiler's barking: "Encountered "SIZE" at character 31, but expected: ["AVG", "COUNT", "KEY", "MAX", "MIN", "SUM", "VALUE", ]." 好吧,编译器咆哮:“遇到”SIZE“在31号,但预期:[”AVG“,”COUNT“,”KEY“,”MAX“,”MIN“,”SUM“,”VALUE“,]。” while parsing JPQL...." 解析JPQL时....“

SIZE is a function that doesn't conform to the specification of the ORDER BY clause: SIZE是一个不符合ORDER BY子句规范的函数:

The ORDER BY clause allows the objects or values that are returned by the query to be ordered. ORDER BY子句允许对查询返回的对象或值进行排序。 The syntax of the ORDER BY clause is orderby_clause ::= ORDER BY orderby_item {, orderby_item}* orderby_item ::= state_field_path_expression [ASC | ORDER BY子句的语法是orderby_clause :: = ORDER BY orderby_item {,orderby_item} * orderby_item :: = state_field_path_expression [ASC | DESC] It is legal to specify DISTINCT with MAX or MIN, but it does not affect the result. DESC]使用MAX或MIN指定DISTINCT是合法的,但它不会影响结果。 When the ORDER BY clause is used in a query, each element of the SELECT clause of the query must be one of the following: an identification variable x, optionally denoted as OBJECT(x), a single_valued_association_path_expression, or a state_field_path_expression. 当在查询中使用ORDER BY子句时,查询的SELECT子句的每个元素必须是以下之一:标识变量x,可选地表示为OBJECT(x),single_valued_association_path_expression或state_field_path_expression。

Furthermore: 此外:

The SIZE function returns an integer value, the number of elements of the collection. SIZE函数返回一个整数值,即集合的元素数。 If the collection is empty, the SIZE function evaluates to zero. 如果集合为空,则SIZE函数的计算结果为零。


Try this: 尝试这个:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM