2010-04-08 49 views
9

Je tente de créer une requête avec l'API Criteria à partir de JPA 2.0, mais je n'arrive pas à la faire fonctionner.Création de requêtes à l'aide de l'API Criteria (JPA 2.0)

Le problème est avec la méthode conditionnelle "entre". J'ai lu some documentation pour savoir comment je dois le faire, mais puisque je découvre JPA, je ne comprends pas pourquoi cela ne fonctionne pas. D'abord, je ne peux pas voir "creationDate" qui devrait apparaître quand j'écris "Transaction_". Je pensais que c'était peut-être normal, puisque j'ai lu que le métamodèle a été généré à l'exécution, donc j'ai essayé d'utiliser 'Foo_.getDeclaredSingularAttribute (' value ')' au lieu de 'Foo_.value', mais ça ne l'est toujours pas. travailler du tout.

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

que quelqu'un peut me aider à comprendre cela? Merci.

EDIT: voici la source de transaction (presque rien en elle, car il a été généré automatiquement par Netbeans, de ma base de données)

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

peut vous envoyer source 'Transaction' aussi bien? –

+0

S'il vous plaît voir ci-dessous. – Pym

Répondre

7

Je pensais qu'il était peut-être normal, puisque j'ai lu le métamodèle a été générée lors de l'exécution (...)

classes de métamodèle sont générées lors de la compilation en utilisant un traitement d'annotation . En d'autres termes, vous devez activer le traitement des annotations au niveau du compilateur. La documentation Hibernate JPA 2 Metamodel Generator décrit comment faire cela avec Ant, Maven et IDE comme Eclipse ou Idea (l'approche peut être transposée à d'autres fournisseurs). Malheureusement, cette fonctionnalité n'est actuellement pas prise en charge dans NetBeans. Donc utilisez ou configurez l'un des outils de construction mentionnés ou passez à un autre IDE. Par exemple, avec Eclipse, un clic droit sur le projet et aller à compilateur Java> Annotation Traitement et l'activer:

alt text

Ajoutez ensuite le JAR requis (s) de votre fournisseur (voir à la documentation de votre fournisseur JPA pour cette étape) au Factory Path.

+0

Merci! J'ai aussi regardé les nightlies de Netbeans et il semble qu'ils aient implémenté les mêmes fonctionnalités récemment. – Pym

+0

@Pym Bon à savoir (j'ai compris que ce serait disponible dans NB 6.9 qui a été récemment publié en version bêta). Merci pour les commentaires. –

2

Je pense que la partie source de confusion est ici q.where(cb.between(transaction.get(Transaction_.creationDate), startDate, endDate));

Vous doit noter que Transaction_ dans ce cas est une classe de métamodèle canonique instanciée statique, correspondant à la classe d'entité Transaction originale. Vous devez générer la classe Transaction_ en compilant votre classe Transaction à l'aide des bibliothèques JPA. un lien utile est ici pour Eclipse: http://wiki.eclipse.org/UserGuide/JPA/Using_the_Canonical_Model_Generator_%28ELUG%29

Pour IntelliJ IDEA

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

+0

Puis-je créer 'Transaction_' manuellement quelque part? – Pym

+0

Maintenant, sachez comment vous allez créer manuellement le métamodèle canonique. Utilisez-vous un IDE? Si oui, suivez les liens applicables ou pour eclipse, regardez la réponse ci-dessous. Quelle version de Java utilisez-vous? Une compréhension implicite parmi les fournisseurs JPA est qu'ils vont générer un métamodèle en utilisant le processeur d'annotation intégré dans le compilateur Java 6. –

-2

POUR QUERY DATE DE DÉBUT ET DATE DE 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

L'OP voulait utiliser l'API Criteria. – prasopes