java - 使用 Hibernate 实体的域实体?
问题描述
在我目前在 Spring Boot 应用程序中与 DDD 的斗争中,我陷入了僵局。我知道我的域实体不应该与基础设施层(休眠实体所在的位置)有任何联系。当然,我的领域层依赖于 Hibernate 实体的数据来完成它的操作。
因此,在我的应用层,我的服务加载 Hibernate 实体并将其传递到域实体中。
这是我的域实体的示例:
package com.transportifygame.core.domain.objects;
import com.transportifygame.core.domain.OperationResult;
import com.transportifygame.core.domain.constants.Garages;
import com.transportifygame.core.domain.exceptions.garages.NotAvailableSpotException;
import com.transportifygame.core.infrastructure.entities.CompanyEntity;
import com.transportifygame.core.infrastructure.entities.GarageEntity;
import com.transportifygame.core.infrastructure.entities.LocationEntity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@RequiredArgsConstructor
@AllArgsConstructor
public class Garage {
private GarageEntity garage;
public static Integer getAvailableSlots(Garages.Size size) {
switch (size) {
case SMALL:
return Garages.Slots.SMALL;
case MEDIUM:
return Garages.Slots.MEDIUM;
case LARGE:
return Garages.Slots.LARGE;
case HUGE:
return Garages.Slots.HUGE;
}
return 0;
}
public static Double getGaragePriceToBuy(Garages.Size size) {
switch (size) {
case SMALL:
return Garages.Prices.BUY_SMALL;
case MEDIUM:
return Garages.Prices.BUY_MEDIUM;
case LARGE:
return Garages.Prices.BUY_LARGE;
case HUGE:
return Garages.Prices.BUY_HUGE;
}
return 0.0;
}
public static OperationResult<GarageEntity, Object> buy(
Garages.Size size,
CompanyEntity company,
LocationEntity location
) {
// As we had changed the company object, we have to refresh
var newGarage = new GarageEntity();
newGarage.setCompany(company);
newGarage.setLocation(location);
newGarage.setSize(size.ordinal());
newGarage.setSlotsAvailable(Garage.getAvailableSlots(size));
return new OperationResult<>(newGarage, null);
}
public static void hasAvailableSpot(GarageEntity garage) throws NotAvailableSpotException {
if (garage.getSlotsAvailable() == 0) {
throw new NotAvailableSpotException();
}
}
public static OperationResult<GarageEntity, Object> addFreeSlot(GarageEntity garage) {
garage.setSlotsAvailable(garage.getSlotsAvailable() - 1);
return new OperationResult<>(garage, null);
}
public static OperationResult<GarageEntity, Object> removeFreeSlot(GarageEntity garage) {
garage.setSlotsAvailable(garage.getSlotsAvailable() + 1);
return new OperationResult<>(garage, null);
}
}
现在的问题是,这是为域实体提供所需数据的正确方法吗?如果没有,正确的方法是什么?
是否使用工厂来构建基于休眠实体的域实体?域实体应该反映休眠实体属性吗?
我也读过有人使用这种方法在 Hibernate 实体中添加域实体的逻辑,但我认为这不是正确的做法。
解决方案
我建议熟悉 DDD 存储库模式。简而言之,存储库应该模仿内存中的集合来检索和存储您的域对象。
因此,您最终可以通过两种方式使用 hibernate 设计您的应用程序:
编写一个高级存储库接口,为您的域实体公开“查找”、“保存”等。存储库接口和返回的实体应该是“纯域逻辑”。也就是说:没有持久性或休眠问题。在您的情况下,它将是在
Garage
那里实现所有业务方法的对象。在存储库实现(可能位于另一个层/包中)中,您将处理休眠行表示(休眠实体)和实体管理器以完成接口的合同。在您的情况下,这是Garage
对象被映射到 (dumb)并通过orGarageEntity
持久化的地方。EntityManager
Session
您可能会接受一些持久性/休眠泄漏到您的域中。这将导致拥有一个
Garage
域对象,其中包含同一源文件上的所有业务逻辑和 hibernate/jpa 注释(或 xml)(xml 可以是单独的)。在这种情况下,存储库可能是直接的 jpa 存储库实现。
无论如何,DDD 中的逻辑总是相同的:
在应用程序服务(一些GarageService
- 用例的入口点)中,查询存储库以获取在其上执行业务操作的域对象。然后应用服务再次将修改后的实体存储在存储库中。
推荐阅读
- c# - 如何将 ZIP 文件从 API 管理上传到 Blob 存储
- scrapy - 确实scrapy无法检索数据
- javascript - jQuery 验证不起作用,控制台中没有错误
- spring-boot - 骆驼上下文在应用程序启动后立即启动关闭,没有明显的错误
- r - R:地图的Openstreetmap自动绘图透明度
- notepad++ - 如何在 Notepad++ 中用新行替换行尾字符?
- bash - 根据文件名中的日期选择最旧的文件
- javascript - 在已经存在的对象中创建对象数组
- html - 当屏幕太亮时使 html 部分可见
- c# - 将单元格中的数字移动到excel表格的右侧