我有一个从第三方数据库中获取汽车实体的应用程序。我称该实体为ThirdPartyCar
.我的应用程序需要使用ThirdPartyCar
中的数据创建Car
实体。但是,Car
实体还必须从我的应用程序的数据库中派生其部分数据。例如,ThirdPartyCar
的状态可能_BOUGHT
,通过数据库查找,我的应用程序必须转换为Sold
。
我目前有一个Car
构造函数,它有一个ThirdPartyCar
参数。但是Car
构造函数无法填充查找数据,因为它是一个实体,实体不应具有对存储库的引用。因此,我还有一个服务来填充剩余数据:
public class ThirdPartyCar {
@Id
private Long id;
private String vin;
private String status;
// more props + default constructor
}
public class Car {
@Id
private Long id;
private String vin;
private CarStatus status;
// more props (some different than ThirdPartyCar) + default constructor
public Car(ThirdPartyCar thirdPartyCar) {
this.vin = thirdPartyCar.getVin();
// more props set based on thirdPartyCar
// but props leveraging database not set here
}
public class CarStatus {
@Id
private Long id;
private String status;
}
public class CarBuilderService {
private final CarStatusMappingRepository repo;
public Car buildFrom(ThirdPartyCar thirdPartyCar) {
Car car = new Car(thirdPartyCar);
CarStatus status = repo.findByThirdPartyCarStatus(thirdPartyCar.getStatus());
car.setStatus(status);
// set other props (including nested props) that depend on repos
}
}
基于ThirdPartyCar
创建Car
的逻辑位置似乎是构造函数。但是我对回购的需求有一个脱节的方法b/c。我可以应用什么模式,以便在构造函数中创建所有数据,但仍然没有让实体知道存储库?
您应该避免在constructor
中链接来自不同域的两个POJO
类。这两个类应该彼此一无所知。也许它们在两个不同的系统中代表相同的概念,但它们并不相同。
好的方法是创建Abstract Factory
接口,该接口将在应从ThirdPartyCar
创建Car
的任何地方使用:
interface ThirdPartyCarFactory {
Car createNewBasedOn(ThirdPartyCar source);
}
一个实现可能是您的RepositoryThirdPartyCarFactory
:
class RepositoryThirdPartyCarFactory implements ThirdPartyCarFactory {
private CarStatusMappingRepository repo;
private CarMapper carMapper;
public Car createNewBasedOn(ThirdPartyCar thirdPartyCar) {
Car car = new Car();
carMapper.map(thirdPartyCar, car);
CarStatus status = repo.findByThirdPartyCarStatus(thirdPartyCar.getStatus());
car.setStatus(status);
// set other props (including nested props) that depend on repos
return car;
}
}
在上面的实现中,您可以找到知道如何将ThirdPartyCar
映射到Car
CarMapper
。要实现此映射器,您可以使用推土机,Orika,MapStruct或自定义实现。
另一个问题是你是如何得到ThirdPartyCar
对象。如果通过从ThirdPartyRepository
ID
加载它,则可以将抽象工厂更改为:
interface CarFactory {
Car createNew(String id);
}
并按ID
ThirdPartyCar
给定实现加载并将其映射到Car
.一切都被工厂隐藏起来,您可以轻松更换。
另请参阅:
- Java 映射框架的性能