我在Config和ConfigHeaders之间有一对多的关系。 这是Config映射器:
pg_ctl status
这是ConfigHeadersMapper:
@Mapper(componentModel = "spring", uses = {UserMapper.class, ConfigHeadersMapper.class})
public interface ConfigMapper extends EntityMapper<ConfigDTO, Config> {
@Mapping(source = "user.id", target = "userId")
ConfigDTO toDto(Config config);
@Mapping(source = "userId", target = "user")
@Mapping(target = "messages", ignore = true)
Config toEntity(ConfigDTO configDTO);
default Config fromId(Long id) {
if (id == null) {
return null;
}
Config config = new Config();
config.setId(id);
return config;
}
}
当我尝试保存一个新实体(ID为Config&amp; ConfigHeaders的等于null)时,这段代码:
@Mapper(componentModel = "spring", uses = {ConfigMapper.class})
public interface ConfigHeadersMapper extends EntityMapper<ConfigHeadersDTO, ConfigHeaders> {
@Mapping(source = "config.id", target = "configId")
ConfigHeadersDTO toDto(ConfigHeaders configHeaders);
@Mapping(source = "configId", target = "config")
ConfigHeaders toEntity(ConfigHeadersDTO configHeadersDTO);
default ConfigHeaders fromId(Long id) {
if (id == null) {
return null;
}
ConfigHeaders configHeaders = new ConfigHeaders();
configHeaders.setId(id);
return configHeaders;
}
}
保存Config和ConfigHeaders,但ConfigHeaders的config_id(FK)为NULL。
所以我尝试了这段代码:
final Config config = configMapper.toEntity(configDTO);
Config newConfig = configRepository.save(config);
确实使用自动生成的父ID(config_id)保存子项(ConfigHeaders)。
你能告诉我MapStruct的错误吗? 我对这个工具很新,我不相信这是正确的解决方案。我认为以前的代码现在只是一种解决方法。
实际上我已经检查了已经生成的MapStruct实现代码,并且我已经注意到它正确设置了父ID(对于新ID是空的)但是它没有设置与父实体的向后关系。我怎么能通过MapStruct实现这个目标?
提前谢谢
答案 0 :(得分:3)
你也可以使用@Context。这也为您提供了使用EntityManager进行操作的可能性。请查看here示例。
答案 1 :(得分:2)
正如您已注意到,为了让JPA正确执行保存,您需要在ConfigHeader
中设置指向配置的链接。
有两种方法可以实现这一目标:
第一个选项:
您可以使用CollectionMappingStrategy#ADDER_PREFERRED
(请参阅更多here)。为此,您需要添加Config
之类的内容:
public void addHeader(ConfigHeader header) {
this.headers.add(header);
header.setConfig(this);
}
第二个选项:
您在@AfterMapping
中使用ConfigMapper
并在那里设置所有标题的配置。
@AfterMapping
default void linkHeaders(@MappingTarget Config config) {
config.getHeaders().stream().forEach(header -> header.setConfig(config));
}
@sjaak在https://stackoverflow.com/a/48974119/1115491中提出的第三个选项:
您可以使用mapstruct-jpa-child-parent示例中显示的@Context
属性。这与第一个选项具有相同的性能,因为您不必遍历标题两次。这样做的另一个好处是,当您无法向实体添加内容时,可以使用它。
看起来像:
public class ConfigContext {
private Config config;
@BeforeMapping
public void setConfig(@MappingTarget Config config) {
this.config = config;
}
@AfterMapping
public void establishRelation(@MappingTarget ConfigHeader header) {
header.setConfig( header );
}
}
您还需要调整toEntity
方法,以便它们也包含上下文。