null id generated for:class fails on create entities mapped by @MapsId and @PrimaryKeyJoinColumn using cascades

Description

I have two entity classes: Fund and FundMetadata, FundMetadata mapped to Fund as one-to-one relation with @MapsId. When I try to save Fund with populated FundMetadata (by FundServiceImpl#save method) the next exception appears:

Caused by: org.hibernate.id.IdentifierGenerationException: null id generated for:class org.gh.db.persistence.metadata.FundMetadata at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125) at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:827)
@Entity @Table(name = "Fund_Metadata", schema = "metadata") class FundMetadata { private Integer id; private Fund fund; private LocalDateTime externalNotesEditDate; @Id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @MapsId @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "fundId", nullable = false, updatable = false) public Fund getFund() { return fund; } public void setFund(Fund fund) { this.fund = fund; } @Column(name = "externalNotesEditDate", columnDefinition = "datetime", nullable = false) public LocalDateTime getExternalNotesEditDate() { return externalNotesEditDate; } public void setExternalNotesEditDate(LocalDateTime externalNotesEditDate) { this.externalNotesEditDate = externalNotesEditDate; } } @Entity @Table(name = "Fund") class Fund { private Integer entityId; private FundMetadata metadata; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer getEntityId() { return entityId; } public void setEntityId(Integer entityId) { this.entityId = entityId; } @PrimaryKeyJoinColumn @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) public FundMetadata getMetadata() { return metadata; } public void setMetadata(FundMetadata metadata) { this.metadata = metadata; } } @Service class FundServiceImpl implements FundService { private final FundRepository fundRepository; public FundServiceImpl(FundRepository fundRepository) { this.fundRepository = fundRepository; } public Fund save(Fund entity) { final FundMetadata metadata = new FundMetadata(); metadata.setFund(entity); metadata.setExternalNotesEditDate(LocalDateTime.now()); entity.setMetadata(metadata); return fundRepository.save(entity); } }

Activity

Show:

Former user November 1, 2019 at 11:49 PM

It only worked in 5.3.7 due to a bug in Hibernate.

Former user November 1, 2019 at 11:49 PM

This is not a proper mapping for a bidirectional one-to-one association. One side must be mapped with {{mappedBy}}, as suggested by .

Eugene Kortov August 6, 2019 at 7:22 PM

As I can guess after https://hibernate.atlassian.net/browse/HHH-12436 one-to-one mappings don’t work when @OneToOne(mappedBy =””) didn’t provided.

Most probably changing to

@OneToOne(mappedBy = "fund", fetch = FetchType.LAZY, cascade = CascadeType.ALL)

public FundMetadata getMetadata() { return metadata; }

will solve the problem.

I’m not sure yet if it is a bug, or your provided mapping is incorrect. Anyway, from the doc you can see, that with @PrimaryKeyJoinColumnyou have to manually set id for child entity. I guess this stfo answer explaines the

@PrimaryKeyJoinColumn meaning and I guess this annotation is not needed in your example.

 

Please answer if this helped and it will be appreciated if you give code project example like it was given in https://hibernate.atlassian.net/browse/HHH-13413 for example

Rejected

Details

Assignee

Reporter

Worked in

Components

Affects versions

Priority

Created December 20, 2018 at 9:56 AM
Updated November 1, 2019 at 11:51 PM
Resolved November 1, 2019 at 11:49 PM