Inv*_*tor 1 spring-data-jpa mapstruct
我在 Config 和 ConfigHeaders 之间有一对多的关系。这是配置映射器:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
这是 ConfigHeadersMapper:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试保存一个新实体(对于 Config 和 ConfigHeaders 的 id 等于 null)时,这段代码:
final Config config = configMapper.toEntity(configDTO);
Config newConfig = configRepository.save(config);
Run Code Online (Sandbox Code Playgroud)
保存 Config 和 ConfigHeaders 但 ConfigHeaders 处的 config_id (FK) 为 NULL。
所以我尝试了这个代码:
final Config config = configMapper.toEntity(configDTO);
config.getHeaders().stream().forEach(header -> header.setConfig(config));
Config newConfig = configRepository.save(config);
Run Code Online (Sandbox Code Playgroud)
并且确实使用自动生成的父 ID (config_id) 保存子项 (ConfigHeaders)。
你能告诉我我在 MapStruct 上做错了什么吗?我对这个工具很陌生,我不相信这是正确的解决方案。我认为以前的代码现在只是一种解决方法。
实际上,我已经检查了生成的 MapStruct 实现代码,我注意到它正确设置了父 ID(对于新的 ID 为空),但它没有设置与父实体的向后关系。我怎样才能通过 MapStruct 实现这一点?
先感谢您
正如您所注意到的,为了让 JPA 正确执行保存,您需要在ConfigHeader.
有两种方法可以实现这一点:
第一个选项:
您可以使用CollectionMappingStrategy#ADDER_PREFERRED(在此处查看更多信息)。为此,您需要添加以下内容Config:
public void addHeader(ConfigHeader header) {
this.headers.add(header);
header.setConfig(this);
}
Run Code Online (Sandbox Code Playgroud)
第二种选择:
您@AfterMapping在ConfigMapper那里使用并在所有标题上设置配置。
@AfterMapping
default void linkHeaders(@MappingTarget Config config) {
config.getHeaders().stream().forEach(header -> header.setConfig(config));
}
Run Code Online (Sandbox Code Playgroud)
@sjaak 在/sf/answers/3428188361/ 中提出的第三个选项:
您可以使用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 );
}
}
Run Code Online (Sandbox Code Playgroud)
您还需要调整您的toEntity方法,以便它们也包括上下文。
| 归档时间: |
|
| 查看次数: |
3764 次 |
| 最近记录: |