java 使用 Criteria API (JPA 2.0) 创建查询

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2602757/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:59:50  来源:igfitidea点击:

Creating queries using Criteria API (JPA 2.0)

javajpajpa-2.0criteria-apimetamodel

提问by Pym

I'm trying to create a query with the Criteria API from JPA 2.0, but I can't make it work.

我正在尝试使用 JPA 2.0 中的 Criteria API 创建查询,但无法使其正常工作。

The problem is with the "between" conditional method. I read some documentationto know how I have to do it, but since I'm discovering JPA, I don't understand why it does not work.

问题在于“之间”条件方法。我阅读了一些文档以了解我必须如何做,但是由于我发现了 JPA,我不明白为什么它不起作用。

First, I can't see "creationDate" which should appear when I write "Transaction_."

首先,我看不到写“Transaction_”时应该出现的“creationDate”。

I thought it was maybe normal, since I read the metamodel was generated at runtime, so I tried to use 'Foo_.getDeclaredSingularAttribute("value")' instead of 'Foo_.value', but it still doesn't work at all.

我认为这可能是正常的,因为我读到元模型是在运行时生成的,所以我尝试使用 'Foo_.getDeclaredSingularAttribute("value")' 而不是 'Foo_.value',但它仍然根本不起作用。

Here is my code :

这是我的代码:

public List<Transaction> getTransactions(Date startDate, Date endDate) {
    EntityManager em = getEntityManager();
    try {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Transaction> cq = cb.createQuery(Transaction.class);
        Metamodel m = em.getMetamodel();
        EntityType<Transaction> Transaction_ = m.entity(Transaction.class);
        Root<Transaction> transaction = cq.from(Transaction.class);

        // Error here. cannot find symbol. symbol: variable creationDate
        cq.where(cb.between(transaction.get(Transaction_.creationDate), startDate, endDate));

        // I also tried this:
        // cq.where(cb.between(Transaction_.getDeclaredSingularAttribute("creationDate"), startDate, endDate));

        List<Transaction> result = em.createQuery(cq).getResultList();
        return result;
    } finally {
        em.close();
    }
}

Can someone help me to figure this out? Thanks.

有人可以帮我解决这个问题吗?谢谢。

EDIT : here is the Transaction source (almost nothing in it, since it was automatically generated by Netbeans, from my database)

编辑:这是事务源(其中几乎没有,因为它是由 Netbeans 从我的数据库自动生成的)

package projetjava.db;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "transaction")
@NamedQueries({
    @NamedQuery(name = "Transaction.findAll", query = "SELECT t FROM Transaction t"),
    @NamedQuery(name = "Transaction.findById", query = "SELECT t FROM Transaction t WHERE t.id = :id"),
    @NamedQuery(name = "Transaction.findByIDAccount", query = "SELECT t FROM Transaction t WHERE t.iDAccount = :iDAccount"),
    @NamedQuery(name = "Transaction.findByDescription", query = "SELECT t FROM Transaction t WHERE t.description = :description"),
    @NamedQuery(name = "Transaction.findByCreationDate", query = "SELECT t FROM Transaction t WHERE t.creationDate = :creationDate"),
    @NamedQuery(name = "Transaction.findByAmount", query = "SELECT t FROM Transaction t WHERE t.amount = :amount")})
public class Transaction implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "ID")
    private Integer id;
    @Basic(optional = false)
    @Column(name = "IDAccount")
    private int iDAccount;
    @Basic(optional = false)
    @Column(name = "Description")
    private String description;
    @Basic(optional = false)
    @Column(name = "CreationDate")
    @Temporal(TemporalType.DATE)
    private Date creationDate;
    @Basic(optional = false)
    @Column(name = "Amount")
    private double amount;

    public Transaction() {
    }

    public Transaction(Integer id) {
        this.id = id;
    }

    public Transaction(Integer id, int iDAccount, String description, Date creationDate, double amount) {
        this.id = id;
        this.iDAccount = iDAccount;
        this.description = description;
        this.creationDate = creationDate;
        this.amount = amount;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public int getIDAccount() {
        return iDAccount;
    }

    public void setIDAccount(int iDAccount) {
        this.iDAccount = iDAccount;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Transaction)) {
            return false;
        }
        Transaction other = (Transaction) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "projetjava.db.Transaction[id=" + id + "]";
    }

}

采纳答案by Pascal Thivent

I thought it was maybe normal, since I read the metamodel was generated at runtime (...)

我认为这可能是正常的,因为我读到元模型是在运行时生成的(...)

Metamodel classes are generated at compile time using annotation processing. In other words, you need to activate annotation processing at the compiler level. The Hibernate JPA 2 Metamodel Generatordocumentation describes how to do that with Ant, Maven and IDEs like Eclipse or Idea (the approach can be transposed to other providers). Sadly, this feature is currently not supported in NetBeans.

元模型类是在编译时使用注释处理生成的。换句话说,您需要在编译器级别激活注释处理。在Hibernate的JPA 2模型生成文档介绍了如何做到这一点用Ant,Maven和像Eclipse或想法的IDE(这种方法可以调换到其他提供商)。遗憾的是,此功能目前在 NetBeans 中不受支持。

So either use and configure one of the mentioned build tool or switch to another IDE. For example, with Eclipse, right-clickon the project and go to Java Compiler > Annotation Processingand Enable it:

因此,要么使用并配置上述构建工具之一,要么切换到另一个 IDE。例如,使用 Eclipse,右键单击项目并转到Java Compiler > Annotation Processing并启用它:

alt text

替代文字

Then add the required JAR(s) of your provider (refer to the documentation of your JPA provider for this step) to the Factory Path.

然后将您的提供者所需的 JAR(请参阅您的 JPA 提供者的文档以了解此步骤)到Factory Path

回答by ring bearer

I think the confusing part here is q.where(cb.between(transaction.get(Transaction_.creationDate), startDate, endDate));

我认为这里令人困惑的部分是 q.where(cb.between(transaction.get(Transaction_.creationDate), startDate, endDate));

You must note that Transaction_in this case is a static-instantiated, canonical metamodel class corresponding to the original Transaction entity class. You must generate Transaction_class by compiling your Transactionclass using JPA libraries. One useful link is here for eclipse: http://wiki.eclipse.org/UserGuide/JPA/Using_the_Canonical_Model_Generator_%28ELUG%29

您必须注意,Transaction_在这种情况下,是与原始 Transaction 实体类对应的静态实例化的规范元模型类。您必须Transaction_通过Transaction使用 JPA 库编译您的类来生成类。eclipse 的一个有用链接是:http: //wiki.eclipse.org/UserGuide/JPA/Using_the_Canonical_Model_Generator_%28ELUG%29

For intellij IDEA

对于智能 IDEA

http://blogs.jetbrains.com/idea/2009/11/userfriendly-annotation-processing-support-jpa-20-metamodel/

http://blogs.jetbrains.com/idea/2009/11/userfriendly-annotation-processing-support-jpa-20-metamodel/

回答by Guntash

QUERY FOR START DATE AND END DATE IN JPA

在 JPA 中查询开始日期和结束日期

public List<Student> findStudentByReports(String className, Date startDate, Date endDate) {
    System.out
    .println("call findStudentMethd******************with this pattern"
            + className
            + startDate
            + endDate
            + "*********************************************");

    return em
    .createQuery(
            "select attendence from Attendence attendence where lower(attendence.className) like '"
            + className + "' or attendence.admissionDate BETWEEN : startdate AND endDate " + "'")
            .setParameter("startDate", startDate, TemporalType.DATE)
            .setParameter("endDate", endDate, TemporalType.DATE)
            .getResultList();
}