具有 Spring 数据 Jdbc 的映射结构
Mapstruct with Spring Data Jdbc
我正在使用 Spring 数据 Jdbc 并且我有 2 个与参考 ID 相关的聚合。
public class ResourceEntity {
@Id
@With
private final UUID id;
private String institutionId;
private String version;
private Long resourceTypeId;
public class ResourceTypeEntity {
@Id @With
private final Long id;
private String name;
我想将其映射为将被翻译的 GRPC 消息
public class Resource {
private String institutionId;
private String version;
private String name; <-- This should be mapped after lookup the ResourceTypeEntity byId
}
我创建了这样一个 ResourceMapper
@Mapper(unmappedTargetPolicy = org.mapstruct.ReportingPolicy.IGNORE,
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
public interface ResourceMapper {
ResourceMapper mapper = Mappers.getMapper(ResourceMapper.class);
@Mapping(target = "name", source = "resourceTypeId", ????
Resource toResource(ResourceEntity resourceEntity);
List<Resource> toResources(List<ResourceEntity> resourceEntities);
基本上我想使用 resourceTypeRepository.findById(resourceTypeId) 来获取 ResourceTypeEntity 并映射名称。
怎么做?
谢谢
只要您需要自动装配存储库以获取对象及其名称以进行进一步映射,您就没有机会通过接口实现这一点。但是,您可以使用 abstract class
代替,它与 MapStruct class 生成完全兼容,包括 Spring 组件模型。
@Mapper(
componentModel = "spring",
unmappedTargetPolicy = org.mapstruct.ReportingPolicy.IGNORE,
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
public abstract static class ResourceMapper {
@Autowired
private ResourceTypeRepository repository;
public abstract Resource toResource(ResourceEntity resourceEntity);
public abstract List<Resource> toResources(List<ResourceEntity> resourceEntities);
@AfterMapping
public void afterMapping(@MappingTarget Resource resource, ResourceEntity entity) {
long id = resourceEntity.getResourceTypeId();
// Call the repository to fetch ResourceTypeEntity by resourceTypeId
// The method results in Optional<ResourceTypeEntity> so you might want to
// ... throw an exception or use a default value if no entity by id is found
String name = repository.findById(id)
.map(ResourceTypeEntity::getName)
.orElse(null);
resource.setName(name);
}
}
@Autowire
private ResourceMapper resourceMapper;
void foo() {
ResourceEntity resourceEntity = ...
Resource resource = resourceMapper.toResource(resourceEntity);
}
记住这是一个 service 而不仅仅是 entity-dto mapper 只要里面的逻辑不是微不足道的并且取决于数据库连接和数据。我宁愿创建一个 @Service
,它使用 interface ResourceMapper
的方法不获取数据(取而代之的是服务层)但通过 @Context
传递 name
:
Resource toResource(ResourceEntity entity, @Context String name);
@AfterMapping
void toResourceAfterMapping(
@MappingTarget Resource resource, ResourceEntity entity, @Context String name
) {
resource.setName(name);
}
我正在使用 Spring 数据 Jdbc 并且我有 2 个与参考 ID 相关的聚合。
public class ResourceEntity {
@Id
@With
private final UUID id;
private String institutionId;
private String version;
private Long resourceTypeId;
public class ResourceTypeEntity {
@Id @With
private final Long id;
private String name;
我想将其映射为将被翻译的 GRPC 消息
public class Resource {
private String institutionId;
private String version;
private String name; <-- This should be mapped after lookup the ResourceTypeEntity byId
}
我创建了这样一个 ResourceMapper
@Mapper(unmappedTargetPolicy = org.mapstruct.ReportingPolicy.IGNORE,
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
public interface ResourceMapper {
ResourceMapper mapper = Mappers.getMapper(ResourceMapper.class);
@Mapping(target = "name", source = "resourceTypeId", ????
Resource toResource(ResourceEntity resourceEntity);
List<Resource> toResources(List<ResourceEntity> resourceEntities);
基本上我想使用 resourceTypeRepository.findById(resourceTypeId) 来获取 ResourceTypeEntity 并映射名称。
怎么做?
谢谢
只要您需要自动装配存储库以获取对象及其名称以进行进一步映射,您就没有机会通过接口实现这一点。但是,您可以使用 abstract class
代替,它与 MapStruct class 生成完全兼容,包括 Spring 组件模型。
@Mapper(
componentModel = "spring",
unmappedTargetPolicy = org.mapstruct.ReportingPolicy.IGNORE,
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
public abstract static class ResourceMapper {
@Autowired
private ResourceTypeRepository repository;
public abstract Resource toResource(ResourceEntity resourceEntity);
public abstract List<Resource> toResources(List<ResourceEntity> resourceEntities);
@AfterMapping
public void afterMapping(@MappingTarget Resource resource, ResourceEntity entity) {
long id = resourceEntity.getResourceTypeId();
// Call the repository to fetch ResourceTypeEntity by resourceTypeId
// The method results in Optional<ResourceTypeEntity> so you might want to
// ... throw an exception or use a default value if no entity by id is found
String name = repository.findById(id)
.map(ResourceTypeEntity::getName)
.orElse(null);
resource.setName(name);
}
}
@Autowire
private ResourceMapper resourceMapper;
void foo() {
ResourceEntity resourceEntity = ...
Resource resource = resourceMapper.toResource(resourceEntity);
}
记住这是一个 service 而不仅仅是 entity-dto mapper 只要里面的逻辑不是微不足道的并且取决于数据库连接和数据。我宁愿创建一个 @Service
,它使用 interface ResourceMapper
的方法不获取数据(取而代之的是服务层)但通过 @Context
传递 name
:
Resource toResource(ResourceEntity entity, @Context String name);
@AfterMapping
void toResourceAfterMapping(
@MappingTarget Resource resource, ResourceEntity entity, @Context String name
) {
resource.setName(name);
}