在我的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定义正确)。
在调试代码时,它正确地显示发票实体是在文档实体上设置的,但遗憾的是它没有持久化在数据库中。
奇怪的是,我几乎可以肯定,在编码过程中的某个时候,它确实按预期工作。但我不能弄清楚问题出在哪里。帮助将不胜感激。
1条答案
按热度按时间nmpmafwu1#
这是不正确的设置,因为您尚未指定任何内容来设置发票的document_id列-您必须从documentId long中自行设置此列。您必须选择一端具有指向另一端的外键-假定发票具有指向Document的外键,并且也将使用该外键作为其主键。如果是这种情况,则需要:
MappedBy表示另一端控制设置外键值。注意,您的Invoice将不会设置documentId值,您也不需要手动设置它。MapsId注解告诉JPA在生成Document ID时从Document ID中提取值,并将其用于document_id列,同时将设置documentId Long。
这将允许您创建一个新的文档和发票,并且只调用文档上的保存-一次。仅仅向文档添加发票是不够的-发票中的ID完全由Invoice.文档引用控制,因此如果没有设置它,它将保留为空。2您必须自己维护双向关系的两端,以使模型与数据库中所需的内容同步。或者至少设置任何双向关系的拥有方。