解決中の問題
サーブレットとJSPは複数のスレッドで共有されるため、ステートレスである必要があります。は状態を保持するEntityManager
ため、単一のインスタンスを並行スレッドで共有することはできません。
EntityManagerを取得するためのスムーズでシームレスなメカニズムが必要です。できればサーブレットコンテナによって管理されます。
サーブレット-コンテナ管理による永続性コンテキスト
ContainerManagedPersistenceContext
サーブレット/JSPランタイムにを導入しましょう。
すぐに定義します。EntityManager
まず、これを使用してに注入する方法を見てみましょうJSP
。
<%! @Inject
@ContainerManagedPersistenceContext.Qualifier
public EntityManager em;
%>
または、さらに良いのはコントローラーに(データ回復/ビジネスロジックをJSPから分離したいからですよね?):
@Named
@SessionScoped
public class SessionController implements Serializable
{
...
@Inject
@ContainerManagedPersistenceContext.Qualifier
private EntityManager em;
}
しかし、私は(まだ)CDIを利用できません
CDIはないが、JSFはある場合は、コンテキストを古いスタイルの標準JSFとして挿入できます@ManagedProperty
。
@Named
@SessionScoped
public class SessionController implements Serializable
{
...
@ManagedProperty(value = "#{containerManagedPersistenceContext}")
ContainerManagedPersistenceContext cmpContext;
...
public void myMethod() {
EntityManager em = cmpContext.getEntityManager();
try {
...
} finally {
em.close();
}
}
}
そもそもこの取り組みにEntityManager
取り組まなければならないのと同じ理由で、決してどこにもキャッシュ/保存してはならないことを忘れないでください。
トランザクション
EntityTransaction
によって提供されるEntityManager
begin/commit/rollbackを使用します。
EntityTransactionトランザクション=em.getTransaction();
ContainerManagedPersistenceContext
これは、アプリケーションスコープのコントローラーおよびPersistenceContext
:として定義されます。
@PersistenceContext(name = ContainerManagedPersistenceContext.NAME,
unitName = ContainerManagedPersistenceContext.UNIT_NAME)
@ApplicationScoped
public class ContainerManagedPersistenceContext implements Serializable
{
private static final long serialVersionUID = 1L;
// UNITNAME must match persistence.xml: <persistence-unit name="myUnitName">
public static final String UNITNAME = "myUnitName";
public static final String NAME = "persistence/" + UNIT_NAME;
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD,
ElementType.PARAMETER, ElementType.TYPE})
public static @interface Qualifier { }
// Servlets must be stateless (shared across multiple threads).
// EntityManager is not stateless (cannot be shared across threads).
// Obtain Container Managed EntityManager - and do NOT cache.
@Produces @Qualifier
public static EntityManager getEntityManager() throws NamingException
{
EntityManager lookup = InitialContext.doLookup("java:comp/env/" + NAME);
return lookup;
}
}
制限事項
記述されているように、これはサーブレットコンテナ用に特別に名前が付けられたPersistenceContextを定義します。はunitName
パラメータ化されていないため、次のようなレベルの柔軟性は提供されません。
@PersistenceContext(unitName = "unitname")
public EntityManager em;
代替案
サーブレットでPersistenceContextを定義し、JNDI名ルックアップを使用します。