简体   繁体   English

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

[英]Creating queries using Criteria API (JPA 2.0)

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 documentation to 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 + "]";
    }

}

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 Generator documentation describes how to do that with Ant, Maven and IDEs like Eclipse or Idea (the approach can be transposed to other providers). Hibernate JPA 2 Metamodel Generator文档描述了如何使用Ant,Maven和IDE(如Eclipse或Idea)执行此操作(该方法可以转换为其他提供程序)。 Sadly, this feature is currently not supported in NetBeans. 遗憾的是,NetBeans目前不支持此功能。

So either use and configure one of the mentioned build tool or switch to another IDE. 因此,要么使用并配置上述构建工具之一,要么切换到另一个IDE。 For example, with Eclipse, right-click on the project and go to Java Compiler > Annotation Processing and Enable it: 例如,使用Eclipse, 右键单击项目并转到Java Compiler> Annotation Processing并启用它:

替代文字

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

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. 您必须注意,在这种情况下, Transaction_是与原始Transaction实体类对应的静态实例化的规范元模型类。 You must generate Transaction_ class by compiling your Transaction class using JPA libraries. 您必须通过使用JPA库编译Transaction类来生成Transaction_类。 One useful link is here for eclipse: http://wiki.eclipse.org/UserGuide/JPA/Using_the_Canonical_Model_Generator_%28ELUG%29 这里有一个有用的链接:eclipse: http//wiki.eclipse.org/UserGuide/JPA/Using_the_Canonical_Model_Generator_%28ELUG%29

For intellij IDEA 对于intellij 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/

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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