Reputation: 1329
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
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