【问题标题】:Am I using EJBs properly?我是否正确使用 EJB?
【发布时间】:2010-04-24 22:43:32
【问题描述】:

我正在使用 JEE6 堆栈,包括 JPA 2.0、JSF 2.0、EJB 3.1 等。

我的架构设置方式如下:

我有使用 hibernate 作为我的 JPA 提供程序的 JPA 注释 DAO。 我有与我的 facelet/xhtml 页面相对应的 JSF 托管 bean。 我有处理所有数据库请求的 EJB。

我的 XHTML 页面有 JSF EL,它调用我的托管 bean。我的托管 bean 包含对由 EJB 管理的 DAO 实体的引用。例如,我有一个映射到数据库表的用户实体。我有一个用户 EJB,它处理所有返回用户的 CRUD 操作。我有一个编辑用户的页面。高级工作流将是:导航到用户编辑页面 -> EL 调用位于托管 bean 中的加载用户的方法。该方法从 EJB 调用 userEJB.loadUser(user) 以从数据库中获取用户。用户被编辑并提交 -> 在托管 bean 中调用一个函数,该 bean 调用 EJB 中的一个函数来保存用户。等等

我在使用 EJB 访问我的 JSF 页面中的数据时遇到问题。 我在延迟初始化错误方面遇到了很多问题,我认为这是由于我的设置方式造成的。

例如,我有一个客户端实体,它有一个延迟加载的用户列表。为了得到 一个客户端 我在我的 EJB 中调用一个方法,该方法进入数据库,找到一个客户端并返回它。稍后的 我希望访问此客户端用户列表,为此我必须通过调用某种方法返回 EJB 以加载这些用户(因为它们是延迟加载的)。这意味着我必须创建一个方法,例如

public List<User> getUserListByClient(Client c)
{
    c = em.merge(c); return c.getUserList();
}

这种方法的唯一目的是加载用户(我什至不肯定这种方法是好的或有效的)。 如果我自己在做会话管理,我只想让会话对整个请求保持打开状态并直接访问属性,这很好,因为无论如何会话都是打开的,EJB 中似乎还有一层额外的间接层这对我来说很困难。

我确实喜欢 EJB,因为我喜欢它们由容器控制、池化、免费提供事务管理等这一事实。但是,我感觉我使用它们不正确,或者我已经设置了我的 JSF 应用程序不正确。

任何反馈都将不胜感激。

谢谢,

【问题讨论】:

    标签: java jsf ejb-3.0 java-ee-6


    【解决方案1】:

    如果我在做会话管理 我自己,我想离开 为整个请求打开的会话 并直接访问该属性,这 会很好,因为会议会 还是打开

    确实,这就是open session in view 模式(也称为在视图中打开实体管理器)。它也可以与 EJB 一起使用。理想情况下,事务应该在业务层/EJB 中管理,因此可以看出这与纯层架构略有偏差。但它解决了视图中延迟加载的问题,而且很容易。

    否则,您必须确保急切地加载将在事务结束后使用的信息。或者你可能依赖 DTO,但它开始变得很麻烦。

    这里还有两个链接,涵盖该主题并讨论利弊和替代方案:

    【讨论】:

      【解决方案2】:

      您的用法似乎不错。请记住,em.merge(c) 可能会将对客户端 c 所做的更改保存到数据库中。如果您只想获取客户端 c 的用户列表而不保存对客户端 c 所做的更改,那么您可以这样做:

      public List<User> getUserListByClient(Client c)
      {
      
           Client client = em.find(Client.class, c.clientId);
           return client.getUserList();
      
      }
      

      或者更好的是,只需将客户端 ID 发送到 getUserListByClient 而不是传递完整的客户端对象,只是为了节省一点点内存:)

      【讨论】:

        猜你喜欢
        • 2011-02-05
        • 2016-01-24
        • 2014-05-15
        • 2010-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多