EJBセッションBeanにアクセスするときにファサードパターンを使用する理由を尋ねたいと思います。私のNetbeans6.9.1では、New
> Sessions Bean for Entity Classes
、そしてUser
エンティティを選択すると、Netbeansはこのコードを生成します
AbstractFacade.Java
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 T edit(T entity) {
return 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) {
...
}
public int count() {
...
}
そして
UserFacade.Java
package com.bridgeye.ejb;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
public class UserFacade extends AbstractFacade<User> {
@PersistenceContext(unitName = "Bridgeye2-ejbPU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public UserFacade() {
super(User.class);
}
}
これのメリットは何かをお聞きしたいと思います。 10個のエンティティがある場合、Netbeansは10個のFacadeクラスとAbstractFacadeを生成します。これは私にはやり過ぎのようです。管理対象Bean内のどこかで、persist
a User
とSchool
を実行する必要があるとしましょう。
someManagedBean.Java
...
@EJB
private UserFacade userEJB;
@EJB
private SchoolFacade schoolEJB;
...
public void someMethod(User user, School school){
...
userEJB.create(user);
schoolEJB.create(school);
}
これは正しいことですか?
EJBを使用するポイントは、アノテーション(またはXML構成)を介して宣言型トランザクションやセキュリティなどの機能を提供することです。これらの機能を使用しない場合、EJBを使用しても意味がありません。
さらに、その自動生成されたファサードコードは、出発点(そして悪いもの)です。 EJBは、個々のCRUD操作すべてのラッパーではなく、ドメインAPIを形成する必要があります。これらには、ドメインモデルで実際に実行する必要のある操作のみが含まれている必要があり、それらの多くは、トランザクション内で実行する必要のあるいくつかのCRUD操作にまたがる必要があります。例えば:
@TransactionAttribute
public void transferUser(User u, School from, School to){
from.getUsers().remove(u);
to.getUsers().add(u);
u.setSchool(to);
getEntityManager().merge(from);
getEntityManager().merge(to);
getEntityManager().merge(u);
}
アプリサーバーはトランザクション内のすべての操作を実行します。これにより、たとえば、何らかの理由で例外がスローされ、ユーザーが1つのSchooldから削除されたが、他のSchooldには追加されないという状況が発生することはありません。 。
はいといいえ。ファサードパターンは非常に理にかなっていますが、ドメインオブジェクトごとに個別のファサードを持つことは意味がありません。
ドメインオブジェクトの機能のグループごとにファサードをグループ化する必要があります。課金システムを想像してみてください。請求書、アイテム、顧客、住所があります。したがって、請求書処理(アイテムの追加、顧客の設定、印刷、有料としてのマーク付け)用のファサードと、ユーザーの作成と更新、住所への関連付けなどのための別のファサードがあります。
ご覧のとおり、一般的なCRUD操作用に1つのAbstractFacadeと、特定のエンティティを操作するための多くのSpecificFacadeが必要だと思います。したがって、同じ基本ロジックを1回だけ再実装することはできず、エンティティに関連付けられたより複雑なロジック(トランザクション)のみに集中できます。