JPA2EclipseLinkを使用してデータベース上で動作するJavaEEWebアプリケーションを作成しています。また、アプリケーション管理のエンティティマネージャーを使用しているので、手動でトランザクションを設定できますが、いくつかのことについてはよくわかりません。
初期情報(詳細/設計部分があるため、この投稿の目的でのみ)JPAエンティティがあります:UserEntityとUserDetailsEntity新しいユーザーを作成するときに、一緒にリンクされている両方のエンティティのインスタンスを作成する必要があります。
ウィザードを使用してエンティティクラスからJSFページを作成しているときに、NetBeansがAbstractFacade
そのFacadeを実装するEnterpriseJavaBeanをUserFacade
作成していることに気付きましたUserDetailsFacade
。これらのEJBは、JPACRUD操作の基本的なラッパーです。
質問:
ファサードパターンは、特に特定のトランザクションでいくつかのJPA操作を組み合わせたい場合に、本当に役立ちますか?このパターンは私のデザインにとって良い/悪いですか、そしてその理由は何ですか?
「UserManagementのトランザクションプロセス」がある場合、トランザクションメカニズムは機能しますが、トランザクションブロック内から直接.persistを実行する代わりに、ラッパーメソッドを実行しています。
utx.begin(); userFacade.create(userEntity); userDetailsFacade.create(userDetailsEntity); utx.commit();
EntityManagerについてよくわかりませんが、複数のインスタンスを作成する必要がありますか?ユーザー認証(現在ログインしているユーザーを知るため)を除いて、EntityManagerのインスタンスを1つ保持する理由がわかりません。EntityManagerFactoryを使用して、必要なときにいつでもインスタンスを取得できると思います。しかし、私が懸念しているのは、ここでのパフォーマンスと良い/悪い設計手法です。または、1つのEntityManagerを保持する必要があります(構成クラスのどこかで取得され、シングルトンまたはCDIを介して共有されますか?)
次のような構造を持つのは良い設計でしょうか:フォーム付きのJSFページ->ManagementBeanが情報を収集して適切なEJBBeanに渡す->EJB Beanはビジネスメソッドを実行し、CRUDを担当するFacadeEJBに情報を渡す->FacadeEJBs情報を永続化します。
AbstractFacadeのコード:(ドラフト)
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0]);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
UserFacadeのコード(ドラフト、CDIを使用するのではなくファクトリからEntityManagerを取得するようにこのクラスを変更するため):
@Stateless
public class UserEntityFacade extends AbstractFacade<UserEntityEntity> {
@PersistenceContext(unitName = "FMSBetaPU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public TestEntityFacade() {
super(TestEntity.class);
}
}
UserManagement EJBのコード(ドラフト)
@Stateless
public class UserManagement {
@Resource
private UserTransaction utx;
@EJB
private UserEntityFacade userFacade;
@EJB
private UserDetailsEntityFacade userDetailsFacade;
public void createUser(int id, String name)
{
UserEntity userEntity = new UserEntity(id);
UserDetailsEntity userDetailsEntity = new UserDetailsEntity(name);
try {
utx.begin();
userFacade.create(userEntity);
userDetailsFacade.create(userDetailsEntity);
utx.commit();
}
catch (Exception e) {
try {
utx.rollback();
} catch (IllegalStateException ex) {
Logger.getLogger(UserManagement.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(UserManagement.class.getName()).log(Level.SEVERE, null, ex);
} catch (SystemException ex) {
Logger.getLogger(UserManagement.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}