使用数据库查找从另一种类型的对象创建一种类型的对象



我有一个从第三方数据库中获取汽车实体的应用程序。我称该实体为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映射到CarCarMapper。要实现此映射器,您可以使用推土机,Orika,MapStruct或自定义实现。

另一个问题是你是如何得到ThirdPartyCar对象。如果通过从ThirdPartyRepositoryID加载它,则可以将抽象工厂更改为:

interface CarFactory {
Car createNew(String id);
}

并按IDThirdPartyCar给定实现加载并将其映射到Car.一切都被工厂隐藏起来,您可以轻松更换。

另请参阅:

  • Java 映射框架的性能

最新更新