使用日期字段的JPA Criteria查询的例外情况

时间:2014-01-26 09:20:54

标签: google-cloud-datastore jpa-2.0 criteria datanucleus

我正在尝试使用JPA Criteria构建动态查询,以使用高级搜索表单中的参数从gae-datastore检索数据。表单有五个字段,类型,最小金额,最大金额,从日期和日期。类型,最小和最大金额,工作得很好,但有日期字段我有这个例外

  

SEVERE:javax.persistence.PersistenceException:expected')'在“(DN_THIS.author ='18580476422013912411')AND(DN_THIS.date> = Wed Jan 01 00:00:00 CET 2014)中的字符68)和( DN_THIS.date< = Fri Jan 31 00:00:00 CET 2014)“

这是我的DAO中抛出异常的方法:

    public List<Outlay> findByParameters(String author, String page, String pageSize,  
    String type, String minAmount, String maxAmount, String fromDate, String toDate)
    throws PersistenceException, ParseException {

    EntityManager em = EMF.get().createEntityManager();

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Outlay> cq = cb.createQuery(Outlay.class);
    Root<Outlay> outlay = cq.from(Outlay.class);

    List<Predicate> predicates = new ArrayList<Predicate>();

    if(author != null && !author.isEmpty()) {
        predicates.add(cb.equal(outlay.<String>get("author"), author));
    }

    if(type != null && !type.isEmpty()) {
        predicates.add(cb.equal(outlay.<String>get("type"), type));
    }

    if(minAmount != null && !minAmount.isEmpty()) {                             
        Double min = Double.parseDouble(minAmount);
        predicates.add(cb.ge(outlay.<Double>get("amount"), min));
    }

    if(maxAmount != null && !maxAmount.isEmpty()) {
        Double max = Double.parseDouble(maxAmount);
        predicates.add(cb.le(outlay.<Double>get("amount"), max));
    }

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");

    if(fromDate != null && !fromDate.isEmpty()) {
        Date from = formatter.parse(fromDate);
        log.info("From: " + formatter.format(from));
        predicates.add(cb.greaterThanOrEqualTo(outlay.<Date>get("date"), from));
    }

    if(toDate != null && !toDate.isEmpty()) {           
        Date to = formatter.parse(toDate);          
        log.info("To: " + formatter.format(to));    
        predicates.add(cb.lessThanOrEqualTo(outlay.<Date>get("date"), to));
    }       

    cq.select(outlay).where(predicates.toArray(new Predicate[]{}));

    log.info("Query: " + cq.toString());

    TypedQuery<Outlay> query = em.createQuery(cq);

    Integer index = 0;   
    if(page != null && !page.isEmpty()) {
        index = Integer.parseInt(page);
    }

    Integer step = 10;      
    if(pageSize != null && !pageSize.isEmpty()) {
        step = Integer.parseInt(pageSize);
    }       

    query.setFirstResult(index * step);
    query.setMaxResults(step);

    List<Outlay> outlayList = new ArrayList<Outlay>();

    try {
        outlayList = query.getResultList();         

        log.info("Retrieved " + outlayList.size() + " Outlay");                                                 
    } finally {         
        em.close();
    }

    return outlayList;
}

这是结果查询

  

SELECT DN_THIS FROM com.mycompany.model.Outlay DN_THIS WHERE(DN_THIS.author ='18580476422013912411')AND(DN_THIS.date&gt; = Wed Jan 01 00:00:00 CET 2014)AND(DN_THIS.date&lt; = 2014年1月31日00:00:00 CET)

这是我的实体

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
public class Outlay implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id;

    private String author;
    private String type;
    private Double amount;
    private Date date;
    private String description; 

    Outlay() { }

    public Outlay(String author, String type, Double amount, Date date,
            String description) {
        super();
        this.author = author;
        this.type = type;
        this.amount = amount;
        this.date = date;
        this.description = description;
    }

    public long getId() {
        return id;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Double getAmount() {
        return amount;
    }

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

    @Temporal(TemporalType.DATE)
    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getDescription() {
        return description;
    }

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

    @Override
    public String toString() {
        return "Outlay [id=" + id + ", author=" + author + ", type=" + type
                + ", amount=" + amount + ", date=" + date + "]";
    }   
}

奇怪的是我在DAO中有类似的方法

    public Long countByParameters(String author, String type, String minAmount,  
        String maxAmount, String fromDate, String toDate)
        throws PersistenceException, ParseException {

    EntityManager em = EMF.get().createEntityManager();

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Long> cq = cb.createQuery(Long.class);
    Root<Outlay> outlay = cq.from(Outlay.class);

    List<Predicate> predicates = new ArrayList<Predicate>();

    if(author != null && !author.isEmpty()) {
        predicates.add(cb.equal(outlay.<String>get("author"), author));
    }

    if(type != null && !type.isEmpty()) {
        predicates.add(cb.equal(outlay.<String>get("type"), type));
    }

    if(minAmount != null && !minAmount.isEmpty()) {                             
        Double min = Double.parseDouble(minAmount);
        predicates.add(cb.ge(outlay.<Double>get("amount"), min));
    }

    if(maxAmount != null && !maxAmount.isEmpty()) {
        Double max = Double.parseDouble(maxAmount);
        predicates.add(cb.le(outlay.<Double>get("amount"), max));
    }

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");

    if(fromDate != null && !fromDate.isEmpty()) {
        Date from = formatter.parse(fromDate);
        log.info("From: " + formatter.format(from));
        predicates.add(cb.greaterThanOrEqualTo(outlay.<Date>get("date"), from));
    }

    if(toDate != null && !toDate.isEmpty()) {           
        Date to = formatter.parse(toDate);          
        log.info("To: " + formatter.format(to));            
        predicates.add(cb.lessThanOrEqualTo(outlay.<Date>get("date"), to));
    }       

    cq.select(cb.count(outlay)).where(predicates.toArray(new Predicate[]{}));

    log.info("Query: " + cq.toString());

    Long count = 0l;

    try {           
        count = em.createQuery(cq).getSingleResult();

        log.info("OutlayList " + count + " size");                                                  
    } finally {         
        em.close();
    }

    return count; 
}

这完美无缺。

我的设置是GAE SDK 1.8.9,JPA 2.0,datanucleus-core 3.1.3,datanucleus-jpa-api 3.1.3和datanucleus-appengine-2.1.2。

任何帮助将不胜感激! 提前谢谢。

2 个答案:

答案 0 :(得分:0)

我总是指定参数而不是文字,因为这样你就可以获得查询/语句重用的好处,特别是日期文字,因为数据存储并不普遍支持它们,而参数是

答案 1 :(得分:0)

这是我的解决方案:

DAO课程

    public List<Outlay> findByParameters(String author, String page, String pageSize,  
    String type, String minAmount, String maxAmount, String fromDate, String toDate)
    throws PersistenceException, ParseException {

    EntityManager em = EMF.get().createEntityManager();

    CriteriaBuilder cb = em.getCriteriaBuilder();       
    CriteriaQuery<Outlay> cq = cb.createQuery(Outlay.class);
    Root<Outlay> outlay = cq.from(Outlay.class);

    List<Predicate> predicates = new ArrayList<Predicate>();

    if(author != null && !author.isEmpty()) {
        predicates.add(cb.equal(outlay.get(Outlay_.author), 
            cb.parameter(String.class, "author")));
    }

    if(type != null && !type.isEmpty()) {
        predicates.add(cb.equal(outlay.get(Outlay_.type), 
            cb.parameter(String.class, "type")));
    }

    if(minAmount != null && !minAmount.isEmpty()) {
        predicates.add(cb.ge(outlay.get(Outlay_.amount), 
            cb.parameter(Double.class, "minAmount")));
    }

    if(maxAmount != null && !maxAmount.isEmpty()) {
        predicates.add(cb.le(outlay.get(Outlay_.amount), 
            cb.parameter(Double.class, "maxAmount")));
    }

    if(fromDate != null && !fromDate.isEmpty()) {
        predicates.add(cb.greaterThanOrEqualTo(outlay.get(Outlay_.date), 
            cb.parameter(Date.class, "fromDate")));
    }

    if(toDate != null && !toDate.isEmpty()) {
        predicates.add(cb.lessThanOrEqualTo(outlay.get(Outlay_.date), 
                cb.parameter(Date.class, "toDate")));           
    }

    cq.select(outlay).where(predicates.toArray(new Predicate[]{}));

    TypedQuery<Outlay> query = em.createQuery(cq);

    if(author != null && !author.isEmpty()) {
        query.setParameter("author", author);
    }

    if(type != null && !type.isEmpty()) {
        query.setParameter("type", type);
    }

    if(minAmount != null && !minAmount.isEmpty()) {
        query.setParameter("minAmount", Double.parseDouble(minAmount));
    }

    if(maxAmount != null && !maxAmount.isEmpty()) {
        query.setParameter("maxAmount", Double.parseDouble(maxAmount));
    }

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");

    if(fromDate != null && !fromDate.isEmpty()) {
        query.setParameter("fromDate", formatter.parse(fromDate));
    }

    if(toDate != null && !toDate.isEmpty()) {
        query.setParameter("toDate", formatter.parse(toDate));
    }

    Integer index = 0;   
    if(page != null && !page.isEmpty()) {
        index = Integer.parseInt(page);
    }

    Integer step = 10;      
    if(pageSize != null && !pageSize.isEmpty()) {
        step = Integer.parseInt(pageSize);
    }       

    query.setFirstResult(index * step);
    query.setMaxResults(step);

    List<Outlay> outlayList = new ArrayList<Outlay>();

    try {
        outlayList = query.getResultList();

        log.info("Retrieved " + outlayList.size() + " Outlay");                                                 
    } finally {         
        em.close();
    }

    return outlayList;
}

然后添加了metamodel类:

package com.mycompany.model;

import java.util.Date;

import javax.persistence.metamodel.SingularAttribute;

@javax.persistence.metamodel.StaticMetamodel(com.mycompany.model.Outlay.class)

public class Outlay_ {
    public static volatile SingularAttribute<Outlay, String> author;
    public static volatile SingularAttribute<Outlay, String> type;
    public static volatile SingularAttribute<Outlay, Double> amount;
    public static volatile SingularAttribute<Outlay, Date> date;    
}