You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Jim O'Rourke <ji...@gmail.com> on 2011/04/23 04:57:45 UTC

CriteriaQuery with shared-cache-mode Enabled Not Working

I'm running into a problem where a CriteriaQuery with a single notEqual
predicate is returning all entities, ie not filtering by the predicate.

Looked at the query in the debugger, and it seemed fine.  Translated it to
std sql and ran it in my database, and got what I expected.

So I set shared-cache-mode to NONE in my persistence.xml to check the
openjpa.SQL log entry and/or the database logs to see what was going on, and
the CriteriaQuery began filtering as I originally expected.

Set persistence.xml shared-cache-mode back to DISABLE_SELECTIVE, and the
CriteriaQuery is again NOT filtering.

I'm Using OpenJPA 2.0.1, and I've got ant building the metaModel via
-Aopenjpa.metamodel=true.

Same results whether my properties has openjpa.jdbc.QuerySQLCache set to
true or false.

Anybody else hit this before, or even better not hit this?

Thanks,

Jim





--
View this message in context: http://openjpa.208410.n2.nabble.com/CriteriaQuery-with-shared-cache-mode-Enabled-Not-Working-tp6298760p6298760.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Re: CriteriaQuery with shared-cache-mode Enabled Not Working

Posted by Jim O'Rourke <ji...@gmail.com>.
Been a while, but wanted to update this post in case someone else stumbles
across it.

My issue was definitely not OpenJPA related - running multiple
CriteriaQuery(s) on a JPA only project under every combination of versions
2.0.1 and 2.1, caching on and off, and same or different
EntityManagerFactory(s) returns the expected result.

Rather than spend any more time trying to determine why my use of the jndi
"java:openejb/PersistenceUnit" EntityManagerFactory acted differently under
the 2 versions, I just wrote my CriteriaQuery as an ejb method and am
continuing to use 2.0.1


--
View this message in context: http://openjpa.208410.n2.nabble.com/CriteriaQuery-with-shared-cache-mode-Enabled-Not-Working-tp6298760p6324508.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Re: CriteriaQuery with shared-cache-mode Enabled Not Working

Posted by Pinaki Poddar <pp...@apache.org>.
Good to know that you resolved the problem for now with 2.1.
> But first, there's a nice cold beer with my name on it... 
You make me feel thirsty...

-----
Pinaki 
--
View this message in context: http://openjpa.208410.n2.nabble.com/CriteriaQuery-with-shared-cache-mode-Enabled-Not-Working-tp6298760p6300064.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Re: CriteriaQuery with shared-cache-mode Enabled Not Working

Posted by Jim O'Rourke <ji...@gmail.com>.
Updating the OpenJPA jar to 2.1 in my OpenEJB stack resolved the issue.  All
these tests passed whether shared-cache-mode was enabled or disabled.  All
suite tests passed with the cache enabled, although there seems to be
version differences between 2.1's dependent jars and OpenEJB's
deployed/repackaged versions, so I'm not giving up on 2.0.1 yet...

As an FYI, annotating the entities using
org.apache.openjpa.persistence.DataCache made no difference under 2.0.1.


Pinaki Poddar wrote:
> 
>  I can not determine the core assertion i.e. the 'expect' list and
> 'result' list be equal because how the 'expect' list is formed is not
> visible to me. 
> 
I included the code for building the expect list, the ejb methods do what
they're supposed to do, and expect is what to expect. But I guess that's not
the point. 


Pinaki Poddar wrote:
> 
>   4. Another angle is Prepared Query Cache -- a mechanics used to cache a
> query string when the same query is executed multiple times. It is known
> to cause problems. To keep it out of the equation, switch it off by
>     openjpa.jdbc.QuerySQLCache=false
> 
I usually have that off anyway, was playing with it as part of trying to
figure out what was going on. BTW, when it's on, the log gets littered with
4625  PortfolioData  WARN   [main] openjpa.Runtime - Query "select e from
Account e" is removed from cache  excluded permanently. 
Query "select e from Account e" is not cached because its result is not
obtained by executing a select statement. 
This can happen if the query was evaluated in-memory. The result was
provided by
org.apache.openjpa.datacache.QueryCacheStoreQuery$CachingResultObjectProvider. 
.
 
And the database log shows the queries running regardless of the setting.

As for the meat of your post.  My EJB stack controls jdbc configuration, so
I can't just Persistence.createEntityManagerFactory(...).  I am reasonably
sure my getEMF() will always return the same EntityManagerFactory instance,
so no-can-do on any comparisons with multiple persistence contexts.

So, next step is to create a JPA only project and exercise CriteriaQuery
under 2.0.1.  I'll report back any findings.

But first, there's a nice cold beer with my name on it...

--
View this message in context: http://openjpa.208410.n2.nabble.com/CriteriaQuery-with-shared-cache-mode-Enabled-Not-Working-tp6298760p6299969.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Re: CriteriaQuery with shared-cache-mode Enabled Not Working

Posted by Pinaki Poddar <pp...@apache.org>.
Hi,
  The way I will approach to narrow down the problem is as follows:
   1. Let C be a CriteriaQuery and J be the equivalent JPQL string.
       Do C and J when executed independently in separate persistence
context produce exactly the same result irrespective of shared data cache
settings?
       If they do, then the problem is not specific to CriteriaQuery per se
and lies somewhere else.
       If they do not, then there is a bug in CriteriaQuery especially when
used in conjunction with data cache.

  2.  Is the query result influenced by existing data in the persistence
context?
       To evaluate, use separate ems in your example. em1 to populate the
'expect' list and em2 to populate the 'result' list. The 'result' list can
be populated from both C and J and examine three-way (i.e. the list you
create via PortfoliEntitymanager in first section, result of C's execution
and that of J's execution) to see there is a difference.

  3. Is shared data cache causing the problem?
      Switch off the data cache entirely and test.

  4. Another angle is Prepared Query Cache -- a mechanics used to cache a
query string when the same query is executed multiple times. It is known to
cause problems. To keep it out of the equation, switch it off by
    openjpa.jdbc.QuerySQLCache=false

 I can not determine the core assertion i.e. the 'expect' list and 'result'
list be equal because how the 'expect' list is formed is not visible to me.
But hope that the above steps will help you to narrow down the issue.

-----
Pinaki 
--
View this message in context: http://openjpa.208410.n2.nabble.com/CriteriaQuery-with-shared-cache-mode-Enabled-Not-Working-tp6298760p6299733.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Re: CriteriaQuery with shared-cache-mode Enabled Not Working

Posted by Jim O'Rourke <ji...@gmail.com>.
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&lt;Holding, Account&gt; acctJ = root.join("account",JoinType.INNER);
Join&lt;Account, Category&gt; catJ = acctJ.join("category",JoinType.INNER);
Join&lt;Account, Owner&gt; 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.

Re: CriteriaQuery with shared-cache-mode Enabled Not Working

Posted by Pinaki Poddar <pp...@apache.org>.
Jim,
  A CriteriaQuery or a JPQL string both are internally converted to an
internal query expression tree -- which gets executed. So I am slightly
baffled by your observation and its dependency on data cache settings.
  Here are few suggestions
  1. Once the CriteriaQuery is formed, call toString() to get a stringfied
form. This should be the equivalent JPQL. Now execute the JPQL and see if
you see any difference in result.
  2. See if the CriteriaQuery and JPQL are creating different target SQL or
not.
  3. Switch of DataCache and see if that makes any difference.


  

-----
Pinaki 
--
View this message in context: http://openjpa.208410.n2.nabble.com/CriteriaQuery-with-shared-cache-mode-Enabled-Not-Working-tp6298760p6298779.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.