私は JPA 永続性基準 API の第一人者ではありません。それを使用すると、ひどい頭痛がすることがあります。
昨日、私は新しい非常に奇妙な動作に気付きました。私が投稿するコードは、既存の機能するコードの適応であるため、些細なエラーに焦点を合わせないでください。私はグラスフィッシュ 3.1.1 と対応する Eclipse 永続化プラグインと Mysql DB を使用しています。
さまざまなテーブルからデータをフィルター処理する criteriaQuery を作成しました。この基準クエリが 2 回実行されると、間違った SQL クエリが生成されます。理由がわかりません。
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();
生成されたSQLは
// 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))
なぜそれが起こるのか誰もわからない場合は、もっと簡単な方法で再現することができます.
ありがとうフィリッポ