0

The JPA 2.0 specification mentions in section 6.9 that CriteriaQuery objects are serializable, and hence may outlive any open EntityManagers or EntityManagerFactory instances:

CriteriaQuery objects must be serializable. A persistence vendor is required to support the subse- quent deserialization of a CriteriaQuery object into a separate JVM instance of that vendor’s runt- ime, where both runtime instances have access to any required vendor implementation classes.

The EJB 3.1 specification says in section 21.2.2:

An enterprise bean must not use thread synchronization primitives to synchronize execution of multiple instances, except if it is a Singleton session bean with bean-managed concurrency.

If I have a stateless session bean that wishes to pre-build a bunch of CriteriaQuery objects using a CriteriaBuilder obtained from an injected @PersistenceContext, where should I stash the results?

I can think of the following possibilities but am concerned that all but one run afoul of the "no synchronization primitives" clause above:

  • In a Map that is stored as the value of one of my bean's instance fields, understanding that I'll have to synchronize access to the map. My take: section 21.2.2 violation.

  • In a ConcurrentMap that is stored as the value of one of my bean's instance fields. My take: still a section 21.2.2 violation, as I'm sure the ConcurrentMap implementation synchronizes somewhere.

  • In a @Singleton EJB's instance field somewhere, where the @Singleton exists only to serve as this kind of cache; with bean-managed concurrency this should be legal, but now all my stateless session beans that want to make use of this CriteriaQuery cache have to inject the singleton into themselves...seems like a lot of overhead.

So it sounds like strictly speaking the last option is the only specification-compliant one. Am I correct?

Laird Nelson
  • 15,321
  • 19
  • 73
  • 127

1 Answers1

1

I would consider putting them in a simple static context, accessible from anywhere. The problem lies in initializing them since you need an entity manager instance to do that. Perhaps a singleton ejb for initializing things as described at Call method in EJB on JBoss startup. The singleton could initialize your criteria query cache, which then could serve criteria queries to your DAOs through static context.

Another option would be to use JPQL which has built in support for precompiled queries. Of course you'd lose some advantages of using the criteria API, though I think the main issue (type safety etc.) might be OK since precompiled queries should throw an exception if they are invalid at deploy time rather than runtime.

Community
  • 1
  • 1
Rasmus Franke
  • 4,434
  • 8
  • 45
  • 62
  • Thank you. I would love to use named queries, but the `ORDER BY` clause (among others) is not parameterizable. So I want to build up a collection of `CriteriaQuery` fragments representing the "complicated parts" and then just bolt on any dynamic parts later. – Laird Nelson Jun 25 '12 at 14:37
  • Intersting idea, I've done something similar, building up a complex filter. But I had the CriteriaQuery object as a parameter to the method constructing the knots and bolts. So no performance gain, only nicer code. Be careful so you don't mutate your cached objects :). – Rasmus Franke Jun 25 '12 at 14:41