Here's what I found, with logging for SQL=TRACE
1. Each CriteriaQuery.toString() returns a properly formed jpql string
which, when written as a TypedQuery, generates an SQL statement in the log
and returns the expected result - regardless of the shared-cache-mode
setting.
2. Using MetaModel/Path based CriteriaQueries exhibit the same behavior
under all scenarios as 'standard' Join/Predicate based CriteriaQueries,
although IMHO substantially easier to craft and read.
3. With shared-cache-mode set to NONE each CriteriaQuery generates an SQL in
the log and returns the expected result - all testcases pass.
4.with shared-cache-mode set to DISABLE_SELECTIVE (all entities involved in
these queries are @javax.persistence.Cacheable) only the first testcase
CriteriaQuery generates an SQL and returns the expected results. Subsequent
CriteriaQuery(s) will not produce an SQL, and return the same resultset as
the first, regardless of the predicates involved (all tests have the same
Root class, only the Join and Predicate vary by testcase)
Any testcase when run on it's own will pass. When multiple testcases are
run (I tried multiple orders), The first will pass, and the remaining will
fail due to getting the resultset of the first
Here's a snippet from one of the testcases showing how the CriteriaQuery is
created.
EntityManager em = getEMF().createEntityManager();
assertNotNull(em);
PortfolioEntityManager mgr = getPEMBean();
assertNotNull(mgr);
//static final String representing the Category Name to exclude
Category categoryExcl = mgr.findByName(Category.class, exclCat);
assertNotNull(categoryExcl);
//ditto for Owner
Owner ownerExcl = mgr.findByName(Owner.class, exclOwn);
assertNotNull(ownerExcl);
List<Holding> expect = new ArrayList<Holding>();
for(Account acct : mgr.list(Account.class)){
if(categoryExcl.equals(acct.getCategory()))
continue;
if(ownerExcl.equals(acct.getOwner()))
continue;
expect.addAll(mgr.listHoldings(acct));
}
CriteriaBuilder bldr = em.getCriteriaBuilder();
CriteriaQuery<Holding> cq=bldr.createQuery(Holding.class);
Root<Holding> root = cq.from(Holding.class);
Join<Holding, Account> acctJ = root.join("account",JoinType.INNER);
Join<Account, Category> catJ = acctJ.join("category",JoinType.INNER);
Join<Account, Owner> ownJ = acctJ.join("owner",JoinType.INNER);
List<Predicate> criteria = new ArrayList<Predicate>();
// fyi this will be replacing functionality built around persisted
classname/id filters
criteria.add(bldr.notEqual(catJ.<Integer>get("id"), categoryExcl.getId() ));
criteria.add(bldr.notEqual(ownJ.<Integer>get("id"), ownerExcl.getId()));
cq.where(bldr.and(criteria.toArray(new Predicate[0])));
System.out.println("Here's the CritQry.toStr():'"+cq.toString() +"'");
List<Holding> result = em.createQuery(cq).getResultList();
System.out.println("Returned "+result.size() +" rows");
assertEquals("CritQry Result Count WRONG!", expect.size(), result.size());
A note on getEMF()... The Test class extends an abstract wrapper who's
responsible for initializing the context and providing ejbs via context
lookup. getEMF() uses "java:openejb/PersistenceUnit" (at this point I'm
just doing a prototype that if adopted will move into an ejb with an
injected EntityManager).
My next step will be to see if annotating the entities using
org.apache.openjpa.persistence.DataCache makes any difference.
If not, I think I'll wire up an ejb impl, maybe I shouldn't be using the
emFactory from "java:openejb/PersistenceUnit" (this is the first time I've
ever done that)?
--
View this message in context:
http://openjpa.208410.n2.nabble.com/CriteriaQuery-with-shared-cache-mode-Enabled-Not-Working-tp6298760p6299672.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.