Spring未在拥有方保持双向OneToOne关系

jslywgbw  于 2023-02-03  发布在  Spring
关注(0)|答案(1)|浏览(130)

在我的Spring Boot 项目中,我有一个Document类,它与Invoice类具有双向OneToOne关系,它们共享相同的ID。

文件

public class Document {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private Invoice invoice;

发票

public class Invoice {

    @Id
    @Column(name = "document_id")
    private Long documentId;

    @OneToOne(mappedBy = "invoice")
    @MapsId
    @JoinColumn(name = "document_id")
    private Document document;

文档实体在发票实体之前创建。稍后我通过MapStruct DTOMap创建发票实体。然后保存实体以“生成”document_id值。
保存发票实体后,我将发票实体分配给文档实体,并通过存储库保存文档实体。但是,与发票实体的关系没有持久保存在数据库中
发票实体应该以相应的document_id作为主键来持久化。

服务代码

Invoice newInvoice = invoiceMapper.fromDto(dto);
newInvoice = invoiceRepository.save(newInvoice);
document.setInvoice(newInvoice);
documentRepository.save(document);

发票Map程序

@Mapper(componentModel = "spring", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, uses = {DocumentService.class})
public interface InvoiceMapper {

    @BeanMapping(ignoreByDefault=true)
    @Mapping(source = "document", target = "document")
    Invoice fromDto(Dto dto);

以前,我也尝试在MapStructMap器中Mapdocument_id,但在保存时收到“* 尝试从空的一对一属性分配id *”异常(即使document和document_id定义正确)。
在调试代码时,它正确地显示发票实体是在文档实体上设置的,但遗憾的是它没有持久化在数据库中。
奇怪的是,我几乎可以肯定,在编码过程中的某个时候,它确实按预期工作。但我不能弄清楚问题出在哪里。帮助将不胜感激。

nmpmafwu

nmpmafwu1#

这是不正确的设置,因为您尚未指定任何内容来设置发票的document_id列-您必须从documentId long中自行设置此列。您必须选择一端具有指向另一端的外键-假定发票具有指向Document的外键,并且也将使用该外键作为其主键。如果是这种情况,则需要:

public class Invoice {

    @Id
    @Column(name = "document_id")
    private Long documentId;

    @OneToOne //this is the owning side of the relationship!
    @MapsId
    @JoinColumn(name = "document_id")
    private Document document;
    ..
}

public class Document {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(mappedBy = "document")
    private Invoice invoice;
    ..
}

MappedBy表示另一端控制设置外键值。注意,您的Invoice将不会设置documentId值,您也不需要手动设置它。MapsId注解告诉JPA在生成Document ID时从Document ID中提取值,并将其用于document_id列,同时将设置documentId Long。
这将允许您创建一个新的文档和发票,并且只调用文档上的保存-一次。仅仅向文档添加发票是不够的-发票中的ID完全由Invoice.文档引用控制,因此如果没有设置它,它将保留为空。2您必须自己维护双向关系的两端,以使模型与数据库中所需的内容同步。或者至少设置任何双向关系的拥有方。

相关问题