2016-10-06 6 views
0

最初に、私が明白なことを尋ねる場合、またはご質問が本質的に根本的に愚かである場合には、ごめんなさい。JPAは一度だけクエリを作成します

より多くの学問的質問は、EntityManagerにまたがっているか、それと独立している(名前が付けられているかどうかなど)JPAクエリを作成できるかどうかを知る必要があります。基本的には、は常に実行されます。。私はEnitity ManagerオブジェクトのcreateXXXQueryメソッドからQueryインスタンスを取得することしかできないと理解していますが、まだ別の方法がありますか?

これが何をしようとしていますされているもので、

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(); 
    } 
} 

これは完全に最初の時間を実行します。しかし、2回目は「Entity Manager Closed」と言います。これは、EMのトランザクションスコープが原因であると私は理解しています。

このEMはコンテナ管理(JTA - Spring)のため、トランザクション間で拡張することはできません。また、Session Beanの使用はオプションではありません。では、このクエリを1回だけ作成する方法はありますか?

PS:名前付きクエリとクエリキャッシュは、どこにありますか?名前付きクエリでは、毎回createNamedQueryのように見えます。クエリキャッシュプランとは何ですか?そこには良いドキュメントがありますか?

もう1つの質問は、EMまたは接続(JDBC)でクエリが作成されるのはなぜですか?クエリを準備するためにどのDBと話しているのかを知る必要はありませんか?適切な接続なしで決して実行することができないようになっていますか?

+1

できません。単純な休止状態では、 'DetachedCriteria'を使うことができますが、それでも実行のための' Criteria'インスタンスになる必要があり、 'Session'(またはJPA用語では' EntityManager')が必要です。しかし、なぜあなたはこれをしたいですか?パフォーマンスは向上しません(より多くのメモリが使用されます)。実際のクエリはJDBCドライバによってキャッシュされます(設定されている場合)。 –

+0

@M。 Deinum私はこれを行う必要はありません、ちょうど私が何かを欠場していたかどうか疑問に思う。なぜそれはより多くの記憶を消費するのだろうか?クエリは、私のレポオブジェクトのメンバーですか?パラメータを使用してSQLを変更しても、JDBCドライブはキャッシュされたSQLを使用していませんか? – anchreg

+0

いいえ。 'PreparedStatement'は、バインドされたパラメータを持つクエリではなくキャッシュされるためです。あなたはもっと多くのオブジェクトをメモリに持っているので、より多くのメモリがあります。今は非常に短い寿命のオブジェクトを持っています。これはかなり速くメモリから取り除かれます。 –

答えて

2

各Queryオブジェクトは特定のEntityManagerに関連付けられており、各EntityManagerが1つのJDBC接続に関連付けられているように、別のEntityManagerに再利用することはできません。

名前付きクエリは、コンパイルされたクエリとその有用なメタデータをキャッシュする方法です。通常、em.createQueryを使用すると、毎回解析されます。同じクエリーに再び遭遇する可能性が非常に高いため、キャッシュに関する情報がキャッシュに保持されることがありますが、これは必須ではありません。

クエリは、(Statementを返す)prepareStatementcreateStatementを呼び出すJDBC接続で(前の二つの継承CallableStatement戻る)またはprepareCall(前のものを継承PreparedStatementを返す)によって作成されます。これらのStatementオブジェクトには、別の接続に切り替えるためのインタフェースがありません。ドライバによっては、Javaアプリケーション内またはサーバー上にキャッシュされることがあります。ステートメントは、同じ接続で何回でも再利用できますが、他のものには再利用できません。

+0

ありがとう。だから、私はJPQLのコンパイルを防ぐことはできませんが、名前付きクエリを使用してパフォーマンスを得ることができますか? – anchreg

+0

ハーフ - はい。名前付きクエリでは、パフォーマンスは若干向上しますが、大幅に向上することはありません。 JPAプロバイダは、コンパイルされたものを格納する可能性が高いでしょう。名前で作成するだけです。通常は注釈を使用します。 – coladict

関連する問題