Antho Christen
Antho Christen

Reputation: 1329

JPA create query only once

Firstly, sorry if I am asking the obvious or if the question it is fundamentally dumb in nature.

More an academic question need to know if I can create a JPA query (named or whatever), that spans across or is independent of an EntityManager . Basically, Prepare once run always. I do understand that we can only get a Query instance from the enitity manager objects's createXXXQuery methods, but still, is there another way?

This is what is am trying to do,

public class MyRepo {
 @PersistenceContext
 private EntityManager em;

 private Query aQueryIntentedtoBePreparedOnlyOnce;

 @PostConstruct
 public void prepareMyQuery(){
  aQueryIntentedtoBePreparedOnlyOnce = em.createQuery("...."); // Query with positional params
   }

  public void executeMyQuery(){
   aQueryIntentedtoBePreparedOnlyOnce.getResultList();
  }
 }

This executes perfectly the first time. But, the second time it says "Entity Manager Closed." I understand this is cause the EM is Transaction scoped.

This EM is container managed(JTA - Spring), so I can't extend it across transactions. And, using Session beans is not an option. So, is there a way to create this query only once?

PS : Where do Named queries and query caching come here? with Named queries I still seem to do createNamedQuery every time. And what is query cache plan are there any good docs for it?

One other question, why are queries only created on the EM or on a Connection(JDBC)? Don't I just need to know which DB I'm talking to in-order to prepare a query? It is so that one can never execute one without a proper connection?

Upvotes: 2

Views: 1548

Answers (1)

coladict
coladict

Reputation: 5095

Each Query object is tied to a specific EntityManager and cannot be reused in another, just as each EntityManager is tied to one JDBC connection.

The named queries are a way to cache the compiled queries and useful metadata about them. Normally when you use em.createQuery it parses it every time. It may keep some information about it in a cache, because it's very likely to encounter the same query again, but that's not required.

Queries are created by calling createStatement (returning a Statement), prepareStatement (returning a PreparedStatement which inherits the previous one) or prepareCall (returning a CallableStatement which inherits the previous two) on the JDBC connection. Those Statement objects have no interface to switch to another connection. Depending on the driver, they may be cached within the Java application or on the server. A Statement can be reused as many times as you want on the same connection, but not on others.

Upvotes: 2

Related Questions