【问题标题】:How to map optional ID field to entity?如何将可选 ID 字段映射到实体?
【发布时间】:2020-10-24 09:43:49
【问题描述】:

我有一个名为 Franchise 的实体,这个实体看起来像这样:

@Data
@Entity
@Table(name = "franchises")
public class Franchise {
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Enumerated(EnumType.STRING)
    private FranchiseType type;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "country_id")
    private Country country;
}

我有以下用于创建新特许经营实体的 api 端点:POST /api/franchise 我需要发送的字段是:nametypecountryIdcountryId 是可选字段,在数据库中可以为空(country_id 列)。

我正在使用 mapstruct 将 CreateFranchiseDTO 映射到 Franchise

@Data
public class CreateFranchiseDTO {
    private String name;
    private String type;
    private Long countryId;
}

@Mapper(componentModel = "spring")
public interface FranchiseDTOMapper {

    @Mapping(source = "countryId", target = "country.id")
    Franchise fromCreateFranchiseDTO(CreateFranchiseDTO dto);
}

当我调用上述 api 端点并将countryId 设置为某个整数(存在于countries 表中)时,一切正常。但是,如果我在请求正文中调用没有countryId 字段的端点并且当执行以下代码时,我会得到异常object references an unsaved transient instance

Franchise franchise = franchiseDTOMapper.fromCreateFranchiseDTO(dto);
franchiseRepository.save(franchise);

当我查看调试器时,我可以看到 franchise.getCountry() 等于 Country 对象,所有字段都设置为 NULL 或零/false(原语的默认值)

我有几个选项可以解决这个问题:

  1. 使用@AfterMapping 并检查franchise.getCountry().getId() == null
  2. 在映射器中创建以下方法:Country longToCountry(Long id)

但在我看来,我错过了什么或者我错了。那么如何使用 mapstruct 将可选 ID(关系)映射到字段?

【问题讨论】:

    标签: java spring hibernate jpa mapstruct


    【解决方案1】:

    如果我理解正确,你和this person有同样的问题。

    似乎对那个人有用的是使用optional = true

    @ManyToOne(optional = true, fetch = FetchType.LAZY)
    

    【讨论】:

    • optional = true 是默认值
    • 啊,你是对的。似乎我在回答之前没有做好我的研究。对于任何好奇的人,here 是一些文档
    猜你喜欢
    • 2021-07-23
    • 2019-08-10
    • 2020-01-27
    • 1970-01-01
    • 2018-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多