【问题标题】:Spring entities and business logic?Spring实体和业务逻辑?
【发布时间】:2017-07-19 17:02:13
【问题描述】:

我正在开发一个 spring 应用程序,与大多数其他 spring 应用程序一样,我有三层。前面是 Rest Controller,中间是 Services,后面是 JPA 存储库。现在我们有映射到数据库的spring实体,在我的例子中,它们是普通的旧java对象(PO​​JO),只有一些我通常喜欢并且不想在其中放置任何业务逻辑的字段和getter和setter。但是,在这个项目中,我发现在很多服务中我都在重复相同的代码,类似这样的代码

User user=userRepository.findUserByName("some name here");
if(user==null){
   throw new UserNotFoundException("User not found");
}

现在,这不仅适用于单个实体,还有许多其他类似的重复部分。因此,我开始担心它并寻找可能的区域来推送该代码并消除重复的部分。如领域驱动设计中所述,有一件事情是有意义的,将业务逻辑放在实体中,现在它们将同时拥有数据和部分业务逻辑。这是一种常见的做法吗?

【问题讨论】:

  • 这个问题太笼统了,你基本上是在问应用DDD的优缺点。
  • 是的,这太面包了。我将缩小范围,将部分业务逻辑放在实体类中,同时将大部分业务逻辑保留在服务中,这是一种常见的做法吗?
  • 一般来说,您将写入/更新的逻辑放在实体中,将查找的逻辑放在存储库中。在CQRS 中,这是非常明确的(根据定义)。

标签: java spring spring-mvc spring-data-jpa domain-driven-design


【解决方案1】:

看起来很像一个简单的代码重用问题。如果您总是在所有上下文中抛出相同的异常,那么在存储库上实现一个findExistingUserByName 方法会在用户不存在时抛出吗?

您的代码将变为:

User user = userRepository.findExistingUserByName("username");

如果您不想更改存储库合同,您还可以在应用程序级别实现 UserFinderService,它包裹 UserRepository 并提供该服务级别的行为。

另一个更通用的想法可能是实现一个通用方法,并通过继承、组合或静态类将其提供给您的应用程序服务,这将允许您执行以下操作:

withExistingAggregate<User>(userRepository.findUserByName("username"), (User user) -> ...)

【讨论】:

  • 好点非常感谢你,但是把它放在实体本身呢?常见的做法是什么?如果我将业务逻辑放在实体类中会破坏什么?
  • 我不确定我是否看到了如何将该逻辑放入实体中,因为如果找不到用户,则不会实例化任何用户。您的意思是将该逻辑封装在User 类的static 方法中吗?这将违反单一责任原则,并且根本没有凝聚力。 User 类是用户概念的抽象,而不是用户存储和检索的抽象(这已经是存储库的角色)。
  • 有些人可能会进一步争辩说,当找不到用户时抛出异常是应用程序级别的问题,因为它与工作流有关。如果您坚持这种思维方式,那么您也将避免将该逻辑放入存储库中。
【解决方案2】:

在这种情况和类似情况下,您可以从存储库中返回 Optional&lt;User&gt;。 然后您的服务代码将如下所示:

userRepository.findUserByName("some name here")
.ifPresent(user -> doThmsWithUser(user));

【讨论】:

  • 是的,但我仍然必须在我的服务类中进行 if 检查并抛出异常。因此,可选并没有让生活变得更轻松。对于 null,它是可选的 null 检查,我需要检查值是否存在。无论哪种情况,它都会以 NPE 为 null 或 Value not present for Optional。
  • 如果你使用Optional,它会抛出 NoSuchElementException 而不是 null 值。
  • NoSuchElementException 只有在你试图从空的Optional 中获取某些东西时才会得到,在上面的代码中没有get
  • 无论是NoSuchElementException还是NullPointerException,有什么改变吗?你没有得到这个问题。我仍然必须检查我所有的服务类。
  • 我同意,这并不能解决问题的问题,尽管与 Optional 的合同更清晰,所以我仍然会为此目的使用它。
猜你喜欢
  • 1970-01-01
  • 2013-09-14
  • 2012-03-08
  • 1970-01-01
  • 2011-04-15
  • 2013-06-16
  • 2013-11-29
  • 2021-02-14
  • 2017-12-17
相关资源
最近更新 更多