Child being inserted before parent

Trying to setup a unidirectional foreign key constraint. Child is the relationship owner.

When using 5.3.20-Final, the sql generated when saving would be :

Hibernate: select person0_.id as id1_2_0_, person0_.name as name2_2_0_ from person person0_ where person0_.id=?
Hibernate: select personmeta0_.id as id1_3_0_, personmeta0_.note as note2_3_0_ from 
person_metadata personmeta0_ where personmeta0_.id=?
Hibernate: insert into person (name, id) values (?, ?)
Hibernate: insert into person_metadata (note, id) values (?, ?)

After updating to 5.3.21-Final, the sql generated is now:

Hibernate: select person0_.id as id1_2_0_, person0_.name as name2_2_0_ from person person0_ where person0_.id=?
Hibernate: select personmeta0_.id as id1_3_0_, personmeta0_.note as note2_3_0_ from 
person_metadata personmeta0_ where personmeta0_.id=?
Hibernate: insert into person_metadata (note, id) values (?, ?)
Hibernate: insert into person (name, id) values (?, ?)

This is triggering the foreign key constraint since there is no associated person that exists yet when the person_metadata record is inserted. Anyone understand what’s causing this?

Example entities below:
Person:

@Entity
@Table(name = "person")
public class Person {
    @Id
    @Column(name = "id")
    private UUID id;

    @Column(name = "name")
    private String name;

    @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "id")
    @Fetch(FetchMode.JOIN)
    private PersonMetadata metadata;

    public UUID getId(){
        return id;
    }

    public void setId(UUID id){
        this.id = id;
    }
    public String getName(){
        return name;
    }
    public PersonMetadata getMetadata(){
        return metadata;
    }

    public void setName(String name){
        this.name = name;
    }

    public void setMetadata(PersonMetadata metadata){
        this.metadata = metadata;
    }

Person_Metadata:

@Entity
@Table(name = "person_metadata")
public class PersonMetadata {
    @Id
    @Column(name = "id")
    private UUID id;


    @Column(name = "note")
    private String note;


    @OneToOne()
    @PrimaryKeyJoinColumn
    //@JoinColumn(name="person_id", referencedColumnName = "id")
    private Person person;


    public UUID getId(){
        return id;
    }

    public void setId(UUID id){
        this.id = id;
    }

    public String getNote(){
        return note;
    }

    public void setNote(String note){
        this.note = note;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person){
        this.person = person;
    }
}

test case:

	@Test
	void savePersonAndMetadata() {
		UUID id = UUID.randomUUID();
		Person testPerson = new Person();
		testPerson.setId(id);
		testPerson.setName("Foo");
		PersonMetadata personMetadata = new PersonMetadata();
		personMetadata.setId(id);
		personMetadata.setNote("Bar");
		testPerson.setMetadata(personMetadata);
		personRepository.save(testPerson);
	}

The foreign key constraint is defined in a liquibase changelog in the person_metadata table:

<addForeignKeyConstraint baseColumnNames="id"
                                 baseTableName="person_metadata"
                                 constraintName="fk_person_metadata_id_person_id"
                                 onDelete="CASCADE"
                                 referencedColumnNames="id"
                                 referencedTableName="person"/>

This is not unidirectional, but a bidirectional association. PersonMetadata#person must be annotated with @OneToOne(mappedBy = "metadata")

Good point, how would you approach if the annotations were changed like this?
Person:

@OneToOne()
@PrimaryKeyJoinColumn
private PersonMetadata personMetadata;

and PersonMetadata had no reference to Person at all

I don’t understand the question. Do you see an exception with this configuration?

Yes, what ends up happening is that the metadata object is inserted into the DB before the person object. Because of the foreign key, an exception is thrown that it is violating the foreign key constraint. Not sure why the metadata object is inserted first. I thought it would be parent before child.

I don’t know how your real model looks like, but the things you posted so far are tested here: hibernate-orm/OneToOneTest.java at 5.3 · hibernate/hibernate-orm · GitHub