2010-04-08 12 views
9

Estoy intentando crear una consulta con la API de Criteria desde JPA 2.0, pero no puedo hacerlo funcionar.Creación de consultas utilizando Criteria API (JPA 2.0)

El problema es con el método condicional "entre". Leí some documentation para saber cómo tengo que hacerlo, pero desde que descubro JPA, no entiendo por qué no funciona.

Primero, no puedo ver "creationDate" que debería aparecer cuando escribo "Transaction_".

Pensé que era tal vez normal, ya que leí que el metamodelo se generó en tiempo de ejecución, así que traté de usar 'Foo_.getDeclaredSingularAttribute ("value")' en lugar de 'Foo_.value', pero aún no lo hace trabajo en absoluto.

Aquí está mi código:

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

Alguien me puede ayudar a resolver esto? Gracias.

EDIT: aquí está el origen de la transacción (casi nada en él, ya que fue generado automáticamente por Netbeans, desde mi base de datos)

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

} 
+0

Se puede publicar fuente de 'Transaction' así? –

+0

Por favor, ver más abajo. – Pym

Respuesta

7

pensé que era quizás normal, desde que leí el metamodelo se genera en tiempo de ejecución (...)

clases Metamodel se generan en tiempo de compilación utilizando el procesamiento anotación. En otras palabras, debe activar el procesamiento de anotaciones en el nivel del compilador. La documentación de Hibernate JPA 2 Metamodel Generator describe cómo hacer eso con Ant, Maven e IDE como Eclipse o Idea (el enfoque puede transponerse a otros proveedores). Lamentablemente, esta característica no es actualmente compatible con NetBeans.

Así que use y configure una de las herramientas de compilación mencionadas o cambie a otro IDE. Por ejemplo, con Eclipse, haga clic con en el proyecto e ir a compilador Java> Tratamiento de anotación y permitirle:

alt text

continuación, agregue el JAR requerida (s) de su proveedor (consulte a la documentación de su proveedor de JPA para este paso) al Factory Path.

+0

Gracias! También eché un vistazo a los nightlies de Netbeans y parece que implementaron las mismas funcionalidades recientemente. – Pym

+0

@Pym. Es bueno saberlo (entendí que esto estaría disponible en NB 6.9, que se lanzó recientemente en Beta). Gracias por la respuesta. –

2

Creo que la parte confuso aquí es q.where(cb.between(transaction.get(Transaction_.creationDate), startDate, endDate));

Usted debe tener en cuenta que Transaction_ en este caso es una clase de metamodelo canónico, instanciado estático correspondiente a la clase de entidad de transacción original. Debe generar la clase Transaction_ al compilar su clase Transaction utilizando las bibliotecas JPA. Un enlace útil es aquí para Eclipse: http://wiki.eclipse.org/UserGuide/JPA/Using_the_Canonical_Model_Generator_%28ELUG%29

Para IntelliJ IDEA

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

+0

¿Puedo crear 'Transaction_' manualmente en alguna parte? – Pym

+0

Ahora está seguro de cómo creará a mano el metamodelo canónico. ¿Estás utilizando algún IDE? si es así, siga los enlaces aplicables o para eclipse, eche un vistazo a la respuesta a continuación. ¿Qué versión de Java estás usando? Una comprensión implícita entre los proveedores de JPA es que generarán un metamodelo utilizando el procesador de anotación integrado en el compilador de Java 6. –

-2

consulta para la fecha de inicio y fin en 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(); 
} 
+0

El OP quería usar Criteria API. – prasopes

Cuestiones relacionadas