当前位置: 首页 > 知识库问答 >
问题:

使用MapStruct的Spring数据和JPA一对多

宋铭
2023-03-14

配置和配置头之间有一对多关系。以下是配置映射程序:

@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;
    }
}

以下是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;
    }
}

当我试图保存一个新实体时(html" target="_blank">配置的ID等于null)

final Config config = configMapper.toEntity(configDTO);
Config newConfig = configRepository.save(config);

保存配置和ConfigHeaders,但ConfigHeaders处的配置id(FK)为空。

所以我尝试了以下代码:

final Config config = configMapper.toEntity(configDTO);
config.getHeaders().stream().forEach(header -> header.setConfig(config));
Config newConfig = configRepository.save(config);

并使用自动生成的父ID(config_ID)保存子项(ConfigHeaders)。

你能告诉我Map结构有什么问题吗?我对这个工具很陌生,我不相信这是正确的解决方案。我认为以前的代码现在只是一种解决方法。

实际上,我已经检查了已生成的MapStruct实现代码,并注意到它正确设置了父ID(对于新的ID为null),但它没有设置与父实体的向后关系。我如何通过MapStruct实现这一点?

提前谢谢你

共有2个答案

洪雨石
2023-03-14

你也可以使用@Context。这也让你有可能使用EntityManager做一些事情。看看这里的例子。

吴松
2023-03-14

正如您所注意到的,为了让JPA正确执行保存,您需要在ConfigHeader中设置指向配置的链接。

有两种方法可以实现这一点:

第一个选项:

您可以使用Collection MappingStrategy#ADDER_PREFERRED(在此处查看更多信息)。为此,您需要在Config中添加如下内容:

public void addHeader(ConfigHeader header) {
    this.headers.add(header);
    header.setConfig(this);
}

第二种选择:

您可以在ConfigMapper中使用@AfterMap并在那里的所有标头上设置配置。

@AfterMapping
default void linkHeaders(@MappingTarget Config config) {
    config.getHeaders().stream().forEach(header -> header.setConfig(config));
}

第三个选项由@sjaak在https://stackoverflow.com/a/48974119/1115491:

可以使用mapstruct jpa子父示例中所示的@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 );
    }
}

您还需要将方法调整为实体方法,以便它们也包括上下文。

 类似资料:
  • 在spring数据JPA-Spring Boot应用程序中,我需要在两个表之间进行一对一映射。我在 一对一映射Spring数据示例 它运行良好,并在第二个表(图书详细信息)中插入记录。在我的应用程序中,我需要多次更新第二个表中的记录(如示例中所示,不更新pages列)。 我正在读取book对象,然后更新bookdetail字段,并使用存储库(extends Crudepository)将其保存回原

  • 我正在开发一个使用Spring数据和JPA来实现基于REST的服务的应用程序。我想使用elastcSearch作为索引引擎。我的域对象: 执行时,我得到以下异常:

  • 我希望在消费者和政策这两个实体之间建立一对多关系。一个消费者应该有几个政策。 这是我想要的一个消费JSON对象的例子: 这就是我到目前为止所做的: 政策实体 消费者实体 我想没那么难,但我已经试了几个小时了,还是做不到。我刚到Spring,所以如果有人能帮助我,我会非常感激!

  • 我在OpenJFX中使用Spring JPA。这个项目是JavaFX weaver,只需在pom中添加spring启动数据jpa。 然而,我的Spring JPA的开始时间是15-20秒,在Spring初始化之前,UI不会显示。当用户启动应用程序时,每次都要花很多时间! 作为一种解决方法,我尝试创建一个没有Spring的简单java fx应用程序(在这里使用这个演示),然后从main方法开始,通过

  • 问题内容: 是否可以使用Spring Data JPA(由Hibernate作为JPA提供者支持)并同时直接使用Hibernate? 问题是,当我使用JpaTransactionManager时,无法使用检索当前会话。当我切换到HibernateTransaction Manager时,JPA存储库无法提交更改。 这是我的Spring上下文的一部分(在该上下文中,我无法使用直接的Hibernate

  • 有人知道如何使用Spring数据JPA获得一个列吗?我在我的Spring Boot项目中创建了一个存储库,如下所示,但总是得到