Attempted to assign id from null one-to-one property

Description

catch very unexpected exception while updgrading hibernate version 5.2.12 -> 5.2.15
in scenario when
there are object whith null OneToOne property in database
and it is updated with object with non null OneToOne property.

i create test project to reproduce this case - https://github.com/evg345/spring-data-hibernate-bug

it seems that some versions of Hibernate are broken

  • 5.2.12.Final = GOOD

  • 5.2.13.Final = GOOD

  • 5.2.14.Final = Exception

  • 5.2.15.Final = Exception

  • 5.2.16.Final = Exception

i create test to reproduce https://github.com/evg345/hibernate-test-case-templates/blob/master/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/HHH12436/OneToOnePropertyTestCase.java
and make pulll request also

Environment

Java 1.8, PostgreSQL, H2Database, Spring-Data 2.0.5

Activity

Show:
Christian Ciach
December 19, 2018, 9:05 PM

I realize that the issue tracker is not a support forum, so I want to thank you for your help!

Because this issue is highly visited and even linked from Stackoverflow, please let me show you how I've completely solved the issue for me. Maybe this will be useful for someone visiting later.

@Gail Badner
Your solution looks nice and will probably work, too. But after further investigating my own solution, I noticed that the lazy loading of Schedule.getData() didn't work - even when adding "optional = false" to the @OneToOne annotation. Don't get me wrong: Lazy loading most like also didn't work with my original (invalid) model. But the "FetchType.LAZY" part makes me believe that the original author wants this to work, so I investigated futher into it.

Then I discovered this excellent blog post by the awesome Vlad Mihalcea: https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/

I am sure I've read this blog post several times in the past and modelled quite some entities after this, but forgot about it. Anyway, the blog post shows the very best solution for exactly my use case: A non-optional one-to-one relation with a shared primary key.

Long story short, I've changed my entities to look like this:

This doesn't change the the database schema, works exactly like before and even supports lazy loading. The only difference is the new public method ScheduleData.getSchedule(), but I am completely okay with that.

In fact, I have used the exact same pattern in several other entities over the last few years, so it was high time to finally "fix" this ancient entity

Gail Badner
December 19, 2018, 9:41 PM

, I'm glad you were able to get things working with a proper JPA mapping.

I'm not sure why lazy loading wouldn't work with a required one-to-one in the unidirectional case. That sounds like a bug. Would you mind opening a new jira issue with a test case that reproduces that?

Christian Ciach
December 19, 2018, 9:58 PM

Gail Badner, I don't know if this is actually a bug. Vlad talks about something like this on his blog:

While the unidirectional @OneToOne association can be fetched lazily, the parent-side of a bidirectional @OneToOne association is not. Even when specifying that the association is not optional and we have the FetchType.LAZY, the parent-side association behaves like a FetchType.EAGER relationship.

To be honest, I don't really understand that paragraph.

If no one stops me from doing so (by confirming that this is indeed not a bug), I will try to provide a test case later this week.

Christian Ciach
December 19, 2018, 10:22 PM
Jan-Willem Gmelig Meyling
December 20, 2018, 10:42 AM

@Christian any optional OneToOne association cannot be lazy loaded, because lazy loading requires us to initialize the value with a proxy, which can't be if the value has to be null when there is no value present. So optional OneToOnes are always eagerly fetched. This is why the example from Gail loads the association eagerly and yours lazily.

Assignee

Gail Badner

Reporter

evg345

Fix versions

Labels

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

backportDecision

None

Worked in

5.1.12
5.1.13

Components

Affects versions

Priority

Major
Configure