Java Spring实体和业务逻辑?

Java Spring实体和业务逻辑?,java,spring,spring-mvc,spring-data-jpa,domain-driven-design,Java,Spring,Spring Mvc,Spring Data Jpa,Domain Driven Design,我正在开发一个spring应用程序,与大多数其他spring应用程序一样,我有三层。其余的控制器在前面,服务在中间,JPA存储库在后面。现在我们有了映射到db的spring实体,在我的例子中,它们是普通的旧java对象(POJO),只有一些字段、getter和setter,我通常更喜欢这些字段、getter和setter,不想在其中放入任何业务逻辑。然而,在这个项目中,我发现在很多服务中,我都在重复相同的代码,类似这样的事情 User user=userRepository.findUserBy

我正在开发一个spring应用程序,与大多数其他spring应用程序一样,我有三层。其余的控制器在前面,服务在中间,JPA存储库在后面。现在我们有了映射到db的spring实体,在我的例子中,它们是普通的旧java对象(POJO),只有一些字段、getter和setter,我通常更喜欢这些字段、getter和setter,不想在其中放入任何业务逻辑。然而,在这个项目中,我发现在很多服务中,我都在重复相同的代码,类似这样的事情

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

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

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

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

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

您的代码将变成:

User user = userRepository.findExistingUserByName("username");
如果您不想更改存储库契约,还可以在应用程序级别实现一个
UserFinderService
,它覆盖
UserRepository
,并提供该服务级别的行为

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

withExistingAggregate<User>(userRepository.findUserByName("username"), (User user) -> ...)
withExistingAggregate(userRepository.findUserByName(“用户名”),(User-User)->…)

这是一个太宽泛的问题,你基本上是在问应用DDD的利弊。是的,这太简单了。我将缩小范围,将业务逻辑的一部分放在实体类中,同时将业务逻辑的大部分放在服务中,这是一种常见的做法吗?通常,您将用于写入/更新的逻辑放在实体中,将用于查找的逻辑放在存储库中。在
CQRS
中,这是非常明确的(根据定义)。是的,但我仍然必须在我的服务类中进行if检查并抛出异常。所以,optional并没有让生活变得简单。简单地说,对于null,它是对optional的null检查,我需要检查值是否存在。在任何一种情况下,它都将以NPE表示null或Value not present表示Optional。如果您使用
Optional
它将抛出NoSuchElementException而不是null值。
NoSuchElementException
只有在您试图从空
Optional
中获取内容时,才会得到,在上面的代码中没有
get
无论它是NoTouchElementException还是NullPointerException,它会改变什么吗?你没有回答这个问题。我仍然需要在我所有的服务类中做一个if检查。我同意,这并不能解决问题,尽管使用
Optional
的合同更干净,所以我仍然会使用它。非常感谢你的好意,但是把它放在实体本身呢?通常的做法是什么?如果我把业务逻辑放在实体类中,会有什么问题呢?我不确定你怎么能把逻辑放在实体中,因为如果找不到用户,那么就不会实例化任何用户。您的意思是将该逻辑封装在
用户
类上的
静态
方法中吗?这将违反单一责任原则,根本没有凝聚力。
User
类是对用户概念的抽象,而不是对用户存储和检索的抽象(这已经是存储库的角色)。有些人可能进一步认为,在找不到用户时引发异常是应用程序级的问题,因为它与工作流有关。如果您坚持这种思维方式,那么您也将避免将该逻辑放入存储库。