Jakarta ee 为什么对EJB会话bean使用Facade模式

Jakarta ee 为什么对EJB会话bean使用Facade模式,jakarta-ee,netbeans,ejb,facade,Jakarta Ee,Netbeans,Ejb,Facade,我想问一下,在访问EJB会话Bean时使用Facade模式的原因是什么。在我的Netbeans 6.9.1中,如果我对实体类执行New>Sessions Bean,并假设我选择User Entity,那么Netbeans将生成此代码 AbstractFacade.java public abstract class AbstractFacade<T> { private Class<T> entityClass; public AbstractFacad

我想问一下,在访问EJB会话Bean时使用Facade模式的原因是什么。在我的Netbeans 6.9.1中,如果我对实体类执行New>Sessions Bean,并假设我选择User Entity,那么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() {
        ...
    }

这是正确的做法吗?

是和否。Facade模式很有意义,但每个域对象有一个单独的facace是没有意义的


您将希望按域对象的功能组对立面进行分组。想象一下一个计费系统。它有账单、物品、客户、地址。因此,您可能会有一个用于处理账单的门面,用于添加项目、设置客户、打印、标记为付费,以及一个用于创建和更新用户的不同门面,与地址等关联。

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

此外,自动生成的facade代码是一个起点,也是一个糟糕的起点。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);
}

应用程序服务器将执行事务中的所有操作,例如,你不能因为某种原因抛出异常,最终用户从一个schood中删除,但没有添加到另一个schood中。

我认为你应该有一个抽象外观用于典型的CRUD操作,正如你所看到的,还有许多特定外观用于操作给定的实体。因此,你不能多次重新实现相同的基本逻辑,只需一次。。。只关注与实体相关的更复杂的逻辑事务。

我仍然有点困惑。我创建EJB的原因是因为我需要与JPA交互以执行CRUD,例如持久化、合并或QuerygetResultList,所以在本例中,我应该使用EJB。顺便说一句,我使用@Statsless EJB。你能详细介绍一下你的第二段吗?也许一些示例代码,以便我能看到实际的结构,我将不胜感激。@Harry:你不需要使用EJB来使用JPA,你可以直接访问EntityManager。但是,使用EJB获取事务可能仍然有意义。我再举个例子,谢谢。如果可能的话,您会添加一个如何正确实现EJB的facade模式的示例吗?我将非常感激:上面的方法在您的EJB中,对吗?您可以使用getEntityManager,而不是将EntityManager指定为全局变量,即您有什么样的结构。我正在学习如何正确地构造我的代码,因此如果我的任何问题没有任何意义,请原谅我的无知。@Harry:是的,这是一个EJB方法,否则注释将无效。在实体管理器中使用getter只是我在示例生成代码中所做的事情,以强调相似性。这是因为它是一个抽象的方法,但这并不重要。
someManagedBean.java

...
@EJB
private UserFacade userEJB;

@EJB
private SchoolFacade schoolEJB;

...

public void someMethod(User user, School school){
    ...
    userEJB.create(user);
    schoolEJB.create(school);    
}
@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);
}