【问题标题】:Why use Facade pattern for EJB session bean为什么对 EJB 会话 bean 使用 Facade 模式
【发布时间】:2011-08-03 22:51:44
【问题描述】:

我想问在访问 EJB Session Bean 时使用 Facade Pattern 的原因是什么。在我的 Netbeans 6.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 中的某个地方,我必须 persistUserSchool 然后我必须这样做

someManagedBean.java

...
@EJB
private UserFacade userEJB;

@EJB
private SchoolFacade schoolEJB;

...

public void someMethod(User user, School school){
    ...
    userEJB.create(user);
    schoolEJB.create(school);    
}

这是正确的做法吗?

【问题讨论】:

    标签: jakarta-ee netbeans ejb facade


    【解决方案1】:

    我认为您应该有一个 AbstractFacade 用于典型的 CRUD 操作,如您所见,以及多个 SpecificFacade 用于操作给定实体。因此,您不能多次重复实现相同的基本逻辑......而只专注于与实体关联的更复杂的逻辑(事务)。

    【讨论】:

      【解决方案2】:

      使用 EJB 的关键在于它们通过注释(或 XML 配置)提供声明性事务和安全性等特性。如果您不使用这些功能,那么拥有 EJB 就没有意义。

      此外,自动生成的外观代码只是一个起点(也是一个糟糕的起点)。 EJB 应该形成一个域 API,而不是所有单个 CRUD 操作的包装器。它们应该只包含您实际希望在域模型上执行的操作,其中许多应该跨越需要在事务中执行的多个 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);
      }
      

      应用服务器将执行事务中的所有操作,例如,这可以确保您不会出现由于某种原因引发异常的情况,并且最终用户会从一个 Schoold 中删除但未添加到另一个。

      【讨论】:

      • 我还是有点迷茫。我创建 EJB 的原因是因为我需要与 JPA 交互来执行 CRUD,例如 persistmergeQuery#getResultList,所以在这种情况下,我应该使用 EJB。我使用@Statsless EJB 顺便说一句。您能否详细说明您的第二段,也许是一些示例代码,以便我可以看到实际结构,将不胜感激。
      • @Harry:你不需要使用 EJB 来使用 JPA,你可以直接访问 EntityManager。但是使用 EJB 获取事务可能仍然有意义。我将添加一个示例。
      • 谢谢。如果可能,您会添加一个如何正确实现 EJB 外观模式的示例吗?我将不胜感激:D
      • 上面的方法在你的EJB里面,对吗?您使用 getEntityManager() 而不是将您的 EntityManager 指定为全局变量,您在那里拥有什么样的结构。我正在学习如何正确构建我的代码,所以如果我的任何问题没有任何意义,请原谅我的无知。
      • @Harry:是的,这是一种 EJB 方法(否则,注释将不起作用)。为实体管理器使用吸气剂只是我在您生成的示例代码中所做的事情,以强调相似性。在那里,它已经完成了,因为它是一个抽象方法,但这并不重要。
      【解决方案3】:

      是和不是。 Facade 模式很有意义,但是为每个域对象设置一个单独的 Facade 是没有意义的。

      您需要根据域对象的功能组对外观进行分组。想象一个计费系统。它有账单、物品、客户、地址。因此,您可能会有一个用于账单处理(添加项目、设置客户、打印、标记为已付款)的外观和用于创建和更新用户、与地址关联等的不同外观。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-12
        • 1970-01-01
        • 2014-07-20
        • 1970-01-01
        • 2010-12-13
        • 2016-04-11
        相关资源
        最近更新 更多