我有一个关系(重)数据库模型,其中包含很多表依赖项和外键。 我们选择使用 DTO 是为了简化前端的数据表示并隐藏数据库模式的复杂性。
但是我们有带有嵌套 DTO 的 DTO。我们有 Mapper 实现类,可以使用小型业务/功能逻辑设置数据。
问题是,映射器类调用映射器(等)是否是一个好习惯,还是让主类处理所有映射器类的最佳方式? (例 1 或 2)
示例 1:
@Component
public class ActorMapperImpl implements ActorMapper {
@Autowired
private InsurerMapper insurerMapper;
@Autowired
private PersonMapper personMapper;
@Autowired
private CorrespondentMapper correspondentMapper;
....
@Override
public ActorDto mapToDto(Acteur actor) {
final ActorDto actorDto;
if (actor != null) {
....
actorDto.setPerson(personMapper.personneToPersonDto(actor.getPersonne()));
if (actor.getInsurer() != null) {
actorDto.setInsurer(insurerMapper.entityToDto(actor.getInsurer()));
} else if (actor.getCorrespondantAssureur() != null) {
actorDto.setInsurer(correspondentMapper.correspondentToInsurerDto(actor.getCorrespondantAssureur()));
}
....
// intermediate
final Intermediaire intermediate = actor.getIntermediaire();
if (intermediate != null) {
.....
if (person != null) {
intermediateDto = personMapper.personneToPersonDto(person);
intermediateDto.setQuality(quality);
}
.....
}
.....
示例 2:
@Service
public class FinancialSlipOrchestratorImpl implements FinancialSlipOrchestrator {
.....
@Autowired
private FinancialSlipMapper financialSlipMapper;
@Autowired
private PersonMapper personMapper;
..... some public / private methods
private FinancialSlipDto fullMapToDto(FinancialSlip financialSlip) {
.....
// Financial slip
var financialSlipDto = financialSlipMapper.mapToDto(financialSlip);
// person
financialSlipDto.setIssuerPerson(personMapper.personneToPersonDto(financialSlip.getIssuerPerson()));
....
// RIB
financialSlipDto.setRib(ribMapper.mapToDto(financialSlip.getRib()));
return financialSlipDto;
}
答案 0 :(得分:1)
我认为一个映射器可以调用另一个映射器并认为这是 Blaze-Persistence Entity Views 的完美用例。
我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义的模型之间轻松映射,例如类固醇上的 Spring Data Projections。这个想法是,您可以按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。
您的用例的 DTO 模型可能如下所示,其中包含 Blaze-Persistence Entity-Views:
@EntityView(Acteur.class)
public interface ActorDto {
@IdMapping
Long getId();
String getName();
PersonDto getPerson();
default InsurerDto getInsurer() {
return getMainInsurer() != null ? getMainInsurer(): getCorrespondantAssureur();
}
@Mapping("insurer")
InsurerDto getMainInsurer();
InsurerDto getCorrespondantAssureur();
IntermediaireDto getIntermediaire();
@EntityView(Person.class)
interface PersonDto {
@IdMapping
Long getId();
String getName();
}
@EntityView(Insurer.class)
interface InsurerDto {
@IdMapping
Long getId();
String getName();
}
@EntityView(Intermediaire.class)
interface IntermediaireDto {
@IdMapping
Long getId();
String getName();
Integer getQuality();
PersonDto getPerson();
}
}
查询是将实体视图应用于查询的问题,最简单的就是通过 id 查询。
ActorDto a = entityViewManager.find(entityManager, ActorDto.class, id);
Spring Data 集成允许您像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
最好的一点是,它只会获取实际需要的数据。
如果您也使用 DTO 来刷新更改,您会很高兴听到 Blaze-Persistence Entity-Views 也以非常有效的方式支持这一点。这将使您摆脱所有那些手动编写的映射器:)