Wrong insert order for OneToOne associations

Description

Assume a simple bi-directional one-to-one relation A->B where B is the owning side of the association and A.b has an "all" cascade:

On the database there's then a foreign key constraint on table_b.a_id to table_a.id.

We then create a new instance like this:

With hibernate.order_inserts = false this works as intended, i.e. first A is persisted and then B due to the cascade.

However, with hibernate.order_inserts = true this breaks because the insert actions are incorrectly reordered thus violating the foreign key constraint. The problem seems to be in org.hibernate.engine.spi.ActionQueue.InsertActionSorter# addParentChildEntityNames(AbstractEntityInsertAction, BatchIdentifier) where there's this piece of code:

Here the problem is that the type for A.b is OneToOne which is an EntityType and hence B is assumed to be the parent of A. In a sense this is true since B is the owning side of the association but in terms of insert ordering A is the parent of B, i.e. A must be inserted first (as will be done without reordering).

One way to fix this might be to check for OneToOneType and then for the value of foreignKeyType.

Tested against versions 5.2.5 and 5.2.7 but might fail in others as well.

Environment

Wildfly 10.0

Activity

Show:
Marian Testowy
February 13, 2019, 10:09 AM

This bug has returned in version 5.4.0. Can you also fix this version?

Vlad Mihalcea
February 13, 2019, 10:42 AM

There is a test case for this issue and runs just fine in 5.4.1 and the master branch. Try to create a replicating test case that proves the issue. Or, fork Hibernate ORM, modify an existing test to replicate it, and send a Pull Request.

Daniel Petersson
March 26, 2020, 10:00 AM

Hi. I think that this bug still exists, and have created a project that illustrates this problem.

A simple OneToOne unidirectional mapping with a foreign key constraint. Works in 5.3 but fails in 5.4

Source and instructions at:

Vlad Mihalcea
March 26, 2020, 10:16 AM

The best way to create a test case for Hibernate is to fork the repository and create the test based on some existing one, as explained in this article.

You shouldn’t use frameworks like Spring or Lombok, as they could interfere with the replicating test case.

Once you do that, you should create a new Jira issue, as this one is closed and doesn’t use the same mappings as your own.

Also, your mappings are wrong. The entity you called Child is actually the parent entity. The entity you called Parent is the one that contains the FK, so it should be the child instead.

And, cascading from the child side to the parent is also a mistake. How can a child exist prior to its parent?

And, you are better off using @MapsId instead of @PrimaryKeyJoinColumn. Check out this article for more details.

Now, I’m no longer working on the Hibernate project, so once you add the test case as a Pull Request, someone from the team should review it.

Daniel Petersson
March 26, 2020, 12:59 PM

Thanks for your reply.

I’ll try to make a better test-case to illustrate the different behavior in 5.3 and 5.4.

Assignee

Unassigned

Reporter

Thomas Göttlich

Fix versions

None

Labels

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

Priority

Major
Configure