DDD Java 和 Spring - 存储库返回 Mono/Flux
DDD Java with Spring - Repository returning Mono/Flux
我想知道在我使用 Java 和 Spring Boot 实现的 DDD 项目中实现反应式 Mongo 存储库时遇到的一个问题。假设我们有这样的包结构:
/app
|
|------/application
| |
| |------/order
| |
| |------OrderApplicationService.java
|
|------/domain
| |
| |------/order
| |
| |------Order.java
| |------OrderRepository.java
|
|------/infrastructure
|
|------/mongo
|
|------MongoOrderRepository.java
我 OrderRepository.java 我想要一个方法来保存我的订单:
public interface OrderRepository {
Order save(Order order);
}
并在我的应用服务中使用它:
@Service
public class OrderApplicationService {
private final OrderRepository orderRepository;
public OrderApplicationService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public void createOrder() {
//Dumb order creation
Order createdOrder = clientRepository.save(new Order());
}
}
接下来我想编写 MongoOrderRepository 来实现 OrderRepository。假设我将使用 ReactiveMongoTemplate。问题是它的所有方法 return Flux 或 Mono,所以我无法从 OrderRepository 接口实现我的方法。
我看到的可能的解决方案是:
- 在 OrderRepository return 中创建 'save' 方法一个由
单核细胞增多症。这种方法会用 Reactor 污染域层
特定类型并打破规则说域层应该是
框架代码免费。
- 开发某种包装层,但这会产生一些
样板代码。
- 将 OrderService.java 移动到基础架构层,但这也打破了一些基本的 DDD 概念。
有人看到更好的解决方案吗?
存储库应该与框架代码无关,这是真的,这是一个很好的做法,但你也需要务实,我有我使用 java lambda 的存储库,这是语言级别的框架之一可以争论。
使用 Flux 或 Mono 有什么好处,将它们作为界面的一部分进行宣传有什么好处?如果有 none,那么您可以将实现细节保留在存储库实现中,并使接口不包含反应对象。
但是,如果这需要跨越应用层到端口适配器,那么我认为将它们放入存储库的接口定义中没有任何问题。
也就是说,您可能想检查另一种方法,使用 CQRS 和六边形架构,您可以两全其美:
- 为命令(更新和创建部分)提供一个干净的存储库界面
使用查询服务(如果您在 java 中,则使用普通 POJO,在您的应用程序包中定义)返回查询的 Mono 或 Flux(阅读部分)
OrderApplicationService.java(这里是通过命令创建更新删除)
OrderQueryService.java(这里是阅读部分)
您的应用程序服务包含对您的 OrderRepository 的引用,查询服务不使用存储库,因为它更直接地查询数据库,例如通过 ReactiveMongoTemplate。
在我的查询服务中,我使用普通 JDBC 模板,例如在存储库实现中使用 Hibernate。
我想知道在我使用 Java 和 Spring Boot 实现的 DDD 项目中实现反应式 Mongo 存储库时遇到的一个问题。假设我们有这样的包结构:
/app
|
|------/application
| |
| |------/order
| |
| |------OrderApplicationService.java
|
|------/domain
| |
| |------/order
| |
| |------Order.java
| |------OrderRepository.java
|
|------/infrastructure
|
|------/mongo
|
|------MongoOrderRepository.java
我 OrderRepository.java 我想要一个方法来保存我的订单:
public interface OrderRepository {
Order save(Order order);
}
并在我的应用服务中使用它:
@Service
public class OrderApplicationService {
private final OrderRepository orderRepository;
public OrderApplicationService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public void createOrder() {
//Dumb order creation
Order createdOrder = clientRepository.save(new Order());
}
}
接下来我想编写 MongoOrderRepository 来实现 OrderRepository。假设我将使用 ReactiveMongoTemplate。问题是它的所有方法 return Flux 或 Mono,所以我无法从 OrderRepository 接口实现我的方法。
我看到的可能的解决方案是:
- 在 OrderRepository return 中创建 'save' 方法一个由 单核细胞增多症。这种方法会用 Reactor 污染域层 特定类型并打破规则说域层应该是 框架代码免费。
- 开发某种包装层,但这会产生一些 样板代码。
- 将 OrderService.java 移动到基础架构层,但这也打破了一些基本的 DDD 概念。
有人看到更好的解决方案吗?
存储库应该与框架代码无关,这是真的,这是一个很好的做法,但你也需要务实,我有我使用 java lambda 的存储库,这是语言级别的框架之一可以争论。
使用 Flux 或 Mono 有什么好处,将它们作为界面的一部分进行宣传有什么好处?如果有 none,那么您可以将实现细节保留在存储库实现中,并使接口不包含反应对象。
但是,如果这需要跨越应用层到端口适配器,那么我认为将它们放入存储库的接口定义中没有任何问题。
也就是说,您可能想检查另一种方法,使用 CQRS 和六边形架构,您可以两全其美:
- 为命令(更新和创建部分)提供一个干净的存储库界面
使用查询服务(如果您在 java 中,则使用普通 POJO,在您的应用程序包中定义)返回查询的 Mono 或 Flux(阅读部分)
OrderApplicationService.java(这里是通过命令创建更新删除) OrderQueryService.java(这里是阅读部分)
您的应用程序服务包含对您的 OrderRepository 的引用,查询服务不使用存储库,因为它更直接地查询数据库,例如通过 ReactiveMongoTemplate。
在我的查询服务中,我使用普通 JDBC 模板,例如在存储库实现中使用 Hibernate。