结合 JPA、EJB 和 JSF 托管 bean 的首选设计模式是啥?

Posted

技术标签:

【中文标题】结合 JPA、EJB 和 JSF 托管 bean 的首选设计模式是啥?【英文标题】:What is the preferred design pattern for combining JPA,EJB and JSF managed beans?结合 JPA、EJB 和 JSF 托管 bean 的首选设计模式是什么? 【发布时间】:2010-11-26 00:43:12 【问题描述】:

这是一个设计模式问题。这是场景: 我将 EJB3.0 与 JPA 一起使用。例如,假设我有一个可以属于组的用户。因此,在我的 User 实体中,我有一个方法 getGroups() 可以懒惰地获取组。我有一个 UserDao,它是一个无状态会话 bean,它有一个方法 用户 getUser(int uid)

现在,在我的 JSF 支持 bean 中,我注入了 UserDao 的远程接口并在其上调用 getUser 以获取 User bean。但我无法访问 user.getGroups 因为它是一个分离的实体。所以我可以在这里想到三种方法:

    在我的 dao 方法中,我也急切地获取组,以便它们也可以在远程用户实体中访问。但是这个问题是 Group 本身可能有延迟获取的关系,而那些我也必须急切地获取,而那些可能有更多的延迟获取的关系等等。所以我最终会发送一个重量级的对象,我不需要它的大部分属性。

    我按原样发送用户,并依靠我的客户不对其调用 getGroups。我可以在 userdao 中提供一个单独的方法,即 List getGroupsIds(int userId) 我有一个 GroupDao,它有类似的方法 getGroup(int groupId) 和其他方法来获取惰性关系的 Id。

    第三个选项是根本不发送这些 JPA 实体,而是创建其他 POJO,如 UserInfo、GroupInfo 等,它们只包含每个实体的基本属性并发送这些实体。我可以在 DAO 中使用方法来获取不同关系的这些实体,例如:List getGroupsForUser(int uid)List getUsersInGroup(int gid)

那么哪些是首选模式。还是人们在这里使用的其他模式?

【问题讨论】:

我怀疑顺利集成这些的最简单方法是使用 Seam:jboss.com/products/seam 是的,我对 Seam 知之甚少,这可能是最好的方法,但现在我坚持不使用 Seam 您是在使用特定的 JPA 实现,还是只是一般性地询问。 EclipseLink 和 Kodo 都会按需加载这些。或者开发者可以请求做一个 Eager fetch。 【参考方案1】:

还有第 4 和第 5 个选项 :-)

4) 在相关 API 调用中包含“通胀水平”参数,例如获取用户(ID,通货膨胀水平)。因此,您将委托选择通过线路发送的对象的哪些部分可供使用该对象的客户端使用。您可以根据需要将 invlation 级别说成粗粒度或细粒度。一个典型的例子是 BASIC(仅填充直接属性)、ASSOCIATIONS(基本 + 直接集合/关联)、FULL(整个层次结构 - 所有关联对象)。

5) 您可以编写自己的代理来支持在线延迟初始化。仅当您延迟加载的关联对象(或属性)可能很大但(由客户端)相对很少使用时,此方法才可行。

然后,当然,还有像 skaffman 提到的 Seam :-)

【讨论】:

【参考方案2】:

我目前的项目已经实施了第三个选项。这不好。每次您必须更改 2-3 个班级,而不仅仅是一个班级。字段重复等等。不是一个选项。

如果您真的不需要 User 对象可以急切获取的所有信息,请选择第二个选项。

如果事实证明实际上您一直需要所有用户信息。没有其他人通过远程服务使用您的用户对象,然后使用您的用户对象 - 使用第一个。

那里的另一个解决方案。我也需要更好的。

【讨论】:

第二种方法的问题是我依赖我的客户进行正确的调用,这很危险。客户端不会知道它不应该调用 getGroups。 从公共访问中删除 getGroups()。 我认为这是 JPA(休眠)卡住的地方。听起来不错,但实际上你不能使用任何很酷的功能。【参考方案3】:

为什么用户实例是分离的?如果您真的在使用 JPA,则可以使用活动实例。因此,当getGroups() 被调用时,用户组会被延迟加载。

【讨论】:

它是分离的,因为在 EJB 容器管理的事务中,事务在您退出 EJB 方法时结束,从而破坏了持久上下文并分离了它管理的所有实体。 视情况而定。只是文档中的一小段引用:“在 Java EE 环境中,jta-data-source 和 non-jta-data-source 元素用于指定要使用的 JTA 和/或非 JTA 数据源的全局 JNDI 名称由持久性提供者提供。”

以上是关于结合 JPA、EJB 和 JSF 托管 bean 的首选设计模式是啥?的主要内容,如果未能解决你的问题,请参考以下文章

将 JSF2 托管 pojo bean 传递到 EJB 或将所需内容放入传输对象

Managed Bean中的EJB3.0 @EJB注释JSF2 Websphere 7是不可能的?

使用@EJB 时,每个托管bean 是不是都有自己的@EJB 实例?

通用 JSF 实体转换器 [重复]

Validator JSF 中的 EJB bean

CDI 托管 bean 和 JSF 托管 bean 可以相互通信吗?