Second execution of the same criteriaQuery generates wrong sql

柔情痞子 提交于 2020-01-05 03:06:15

问题


I'm not a JPA persistence criteria API guru and sometimes I get very terrible headaches using it.

Yesterday I noticed a new very weird behaviour. The code I will post is an adaptation of existing functioning code, so don't focus on trivial errors. I'm using glassfish 3.1.1 and the corresponding eclipse persistence plugin and Mysql DB.

I have written a criteriaQuery which filters data from different tables. If this criteriaquery is executed twice the second time it generates wrong SQL query. I cannot figure out why.

public CriteriaQuery createQuery4Count(EntityManager em) {
    Calendar lastDate4Search = GregorianCalendar.getInstance();
    javax.persistence.criteria.CriteriaBuilder cb = em.getCriteriaBuilder();
    javax.persistence.criteria.CriteriaQuery cq = cb.createQuery();
    javax.persistence.criteria.Root<Permessimercepath> checkPointRt = cq.from(Permessimercepath.class);
    javax.persistence.criteria.Path<Permessimerce> permessimerceClass = checkPointRt.get(Permessimercepath_.permessimerce);
    Predicate checkPointDatePredicate = cb.isNull(checkPointRt.get(Permessimercepath_.dataTransito));
    Predicate checkPointAreaPredicate = cb.equal(checkPointRt.get(Permessimercepath_.iDArea), area);
    Predicate datePredicate = cb.greaterThanOrEqualTo(permessimerceClass.get(Permessimerce_.datafine), lastDate4Search.getTime());
    Predicate isValidPredicate = cb.lt(permessimerceClass.get(Permessimerce_.statopermesso), Permessimerce.COMPLETED);
    cq.where(cb.and(checkPointAreaPredicate, checkPointDatePredicate, datePredicate, isValidPredicate));
    cq.select(cb.countDistinct(checkPointRt));
    return cq;
}

 CriteriaQuery myCriteriaQuery = createQuery4Count(getEntityManager())
 javax.persistence.Query q = getEntityManager().createQuery(myCriteriaQuery );
 Long Result = ((Long) q.getSingleResult()).intValue();

 // second query created with the same criteriaQuery 
 q = getEntityManager().createQuery(myCriteriaQuery );
 Long Result2 = ((Long) q.getSingleResult()).intValue();

The generated sql is

// First and correct one
SELECT COUNT(t0.ID_permesso) FROM permessimercepath t0 WHERE EXISTS (SELECT t1.ID_permesso FROM permessimerce t2, permessimercepath t1 WHERE ((((t0.ID_permesso = t1.ID_permesso) AND (t0.CheckPointIndex = t1.CheckPointIndex)) AND ((((t1.ID_Area = ?) AND (t1.DataTransito IS NULL)) AND (t2.Data_fine >= ?)) AND (t2.Stato_permesso < ?))) AND (t2.ID_permesso = t1.ID_permesso))) 
bind => [3 parameters bound]


// Second and wrong one
 SELECT COUNT(t0.ID_permesso) FROM permessimercepath t0, permessimerce t2, permessimercepath t1 WHERE (((((t1.ID_Area = ?) AND (t1.DataTransito IS NULL)) AND (t2.Data_fine >= ?)) AND (t2.Stato_permesso < ?)) AND (t2.ID_permesso = t1.ID_permesso))

If nobody has an idea on why it happens I can try to reproduce it in a simpler way.

Thanks Filippo


回答1:


The problem seems to related with EntityManager.createQuery(CriteriaQuery) method. I checked the documentation, but nothing is mentioned about whether this method modifies CriteriaQuery or not. Normally one expects this method to not modify the passed parameter. However, what you are getting suggests that EntityManager.createQuery(CriteriaQuery) method modifies the passed parameter.

If this is the case you will need to call createQuery4Count(getEntityManager()) before calling EntityManager.createQuery(CriteriaQuery) in your code each time.




回答2:


It looks likely that you spotted bug in implementation. Slightly similar (or so to say more complex but different) case works fine with Hibernate. Also, section "6.8 Query Modification" from JPA Specification encourages reuse of CriteriaQuery:

A CriteriaQuery object may be modified, either before or after TypedQuery objects have been created and executed from it. For example, such modification may entail replacement of the where predicate or the select list. Modifications may thus result in the same CriteriaQuery “base” being reused for several query instances.



来源:https://stackoverflow.com/questions/10648142/second-execution-of-the-same-criteriaquery-generates-wrong-sql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!