【问题标题】:EJBs and JPA design questionEJB 和 JPA 设计问题
【发布时间】:2011-10-05 15:19:11
【问题描述】:

我正在使用 EJB 3.1 和 JPA 2.0。

我会给你一个例子来解释我的疑虑,并寻求提示,什么是好的做法,什么不是。

假设我有一个作为用户外观的 EJB。所以你有这样的东西:

@Stateless
public class UserRepository {

  public User find(Long id) {
    ...do user lookup using entitymanager.
  }

}

好的,现在假设我从这里返回 User 实体,并且该实体有一个 cmets 集合(Comment 也是一个实体)。

我可以有一个带有findCommentsByUser(Long userId) 方法的评论存储库,或者我可以获取用户并调用getComments() 方法。可能这种情况很简单,但我多次面临这个决定,有时不知道什么是最好的。

另外,假设我要添加评论,我应该将其添加到实体拥有的评论集合中并合并实体,还是应该使用addComment(Long userId, Comment newComment) 方法?

我正在寻找有关这方面的建议或最佳做法。如果您需要进一步的说明,请随时询问。

编辑:

到目前为止,我发现 cmets 很有帮助,但是请注意,这实际上与用户和 cmets 无关,我只是为了解释我的情况而编造的。这是关于混合两种方法是否方便(我认为不是),还是一种比另一种更好。我喜欢“始终坚持通过存储库”的建议。但是我有一个fetchComments() 存储库方法和用户实体中的getComments() 的事实创建了相同功能的入口点,那么我该如何处理呢? 此外,性能(1 个查询与 2 个查询)也不是很重要,因为我也会获取用户实体,所以我实际上并没有保存任何东西。

【问题讨论】:

    标签: java design-patterns jpa ejb


    【解决方案1】:

    有几个需要考虑的因素,我希望我会在这里为您记录下来。

    1. 域模型是 EJB3 中的重要考虑因素。在您的示例中,如果您看到您的域模型允许您延迟获取 cmets,因为在任何流程中您首先显示用户详细信息,然后显示他的 cmets。
    2. 在某些情况下,您的集合(我在这里指的是 cmets)可能包含大量数据,在这种情况下,字符串数据几乎不是问题,因此不是主要问题,但如果它是真实的应用程序数据,则始终选择瞬态关系并提供适当的方法来独立获取它们。
    3. 将实体 bean 中的集合暴露给外部世界从来都不是一个好习惯,因此如果您是 OneToMany 或 ManyToMany 关系,那么您应该为集合提供三种基本方法(添加、删除、获取)。
    4. 从 get 方法返回集合时应使用Collections.unmodifiableCollection 方法。
    5. 在实体内部使用集合时始终使用 Set,记住它们不允许重复。
    6. 在您的情况下,cmets 集合直接依赖于用户,因此您应该在用户中使用级联类型来保存 cmets。
    7. 我不相信您为什么需要 UserRepository,因为 em.find 方法会为您完成工作。
    8. 默认情况下,OneToMany 关系的 fetchtype 是惰性的,因此如果您想要进行即时加载,则需要指定它。

    我希望这些指南能够解决您的问题。

    问候, 阿米特

    【讨论】:

      【解决方案2】:

      我可以拥有一个带有 findCommentsByUser(Long userId) 方法,或者我可以获取用户并调用 getComments()

      我会说,从性能的角度来看,第一个替代方案稍好一些,因为您不会先获取用户(1 个查询)然后再获取 cmets(另一个查询)。第一个是一次性完成的。

      另一方面,我发现第二种更可读抽象面向对象的方法。我会用这个。

      【讨论】:

        【解决方案3】:

        我们通常只使用应用程序中的分离实体,因此我们有一个数据访问管理器来获取和更新实体。然后我们知道,除非特别调用,否则我们在业务逻辑中所做的任何事情都不会被持久化。我还将使用用户实体获取 cmets,但要确保它在显式调用之前不会持久化。

        【讨论】:

          【解决方案4】:

          我认为这在很大程度上取决于要求,取决于您希望对流程进行多细粒度控制(这通常取决于性能要求和预期负载等)。 如果永远不会独立检索 cmets,我只会将它们作为参考保留在 User 中。

          但是,如果您想要获取 cmets 而不管用户如何,或者您想要执行一些其他与 cmets 相关的查询(例如 A 组中用户的所有 cmets),那么我将创建单独的 CommentsRepository

          如果您希望能够将评论添加到未从数据库加载的用户,但您有外键,您可能只想像您建议的那样通过 CommentsRepository 添加评论(也添加评论将这两个列表并行保存到用户的 cmets 列表中,并将这两个列表保存到 DB 中可能会导致“奇怪的行为”)。

          【讨论】:

            【解决方案5】:

            您通常会将 getComments() 方法添加到您的用户对象。当您想添加一个时,您会将其添加到用户集,然后在用户对象上调用更新。

            【讨论】:

              猜你喜欢
              • 2011-12-07
              • 2011-04-18
              • 2011-02-03
              • 2012-09-09
              • 1970-01-01
              • 2011-10-27
              • 2011-03-01
              • 1970-01-01
              相关资源
              最近更新 更多