Hibernate @OneToOne with MapsId does not map the same id with the parent entity

Hi,

I have a child entity of which id is mapped with parent id using @MapsId @OneToOne.

I am running Mock Tests with JUnit to confirm the correct behavior of @MapsId @OneToOne, however I am getting difference ids for parent and child, during update case.

I have created a simple project which shows this error.

https://github.com/pmverma/hibernate-mapsid-test

Is this correct behavior?
What I am doing wrong?

Any help is really appreciated.

Regards,
Mohan

Your test is not correct. How could a Child be created without a Parent?

childRepository.saveAndFlush(child);

Parent parent = new Parent();
em.persist(parent);
em.flush();

What would the Child id point to?

Also, you don’t need to Mock the DB. Just use an integration test instead.

This test in the Hibernate ORM project shows that everything works just fine. Try to debug the Hibernate test and see why that one works and yours does not.

Thanks @vlad for quick reply.

I have set the parent in line https://github.com/pmverma/hibernate-mapsid-test/blob/master/src/test/java/com/example/demo/HibernateMapsidTestApplicationTests.java#L54 which is called in @Before so child will already have a parent during saveAndFlush

And here at https://github.com/pmverma/hibernate-mapsid-test/blob/master/src/test/java/com/example/demo/HibernateMapsidTestApplicationTests.java#L87, I want to change the parent. And I assume that child will have the parent which was earlier, not the updated one.

Actually, This is happening while running the integration tests of the project so I setup a similar simple one.

Here is the request/response to update child with new parent.

MockHttpServletRequest:
HTTP Method = PUT
Request URI = /update-child
Parameters = {}
Headers = [Content-Type:“application/json;charset=UTF-8”]
Body = {“id”:1,“parent”:{“id”:2}}
Session Attrs = {}

Handler:
Type = com.example.demo.MyResource
Method = public com.example.demo.Child com.example.demo.MyResource.updateChild(com.example.demo.Child)

Async:
Async started = false
Async result = null

Resolved Exception:
Type = null

ModelAndView:
View name = null
View = null
Model = null

FlashMap:
Attributes = null

MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:“application/json;charset=UTF-8”]
Content type = application/json;charset=UTF-8
Body = {“id”:1,“parent”:{“id”:2}}
Forwarded URL = null
Redirected URL = null
Cookies =

And is response, we are getting the updated parent.

You cannot update the parent was the child was persisted. That would mean to update the PK which is not allowed.

I understand that updating PK is now allowed. But given that the child can set its parent to new, and this results in a new parent for the whole current transaction, how can this should be avoided?

I have done a PR to demonstrate this case at https://github.com/vladmihalcea/high-performance-java-persistence/pull/36

Regards,
Mohan

A shared PK requires the parent to exist. If you want to change the parent, that’s not a one-to-one association, that’s a many-to-one with a unique constraint, meaning you have to remove @MapsId.

Thanks @vlad, I have one question regarding following.

I understand that changing parent is not allowed since PK updating is not allowed. But hibernate does not seems to be aware of the new parent and it is doing em.merge(child) successfully and returning child object with new parent. And this will lead to some subsequent un-intended errors regarding relationships.

I am contributing to add support for @OneToOne relationship with @MapsId in JHipster but I am afraid to continue more because of this issue. Is there any way Hibernate can complain or throws exception during em.merge(child) or anytime because it does not make sense to allow to merge the child with new parent? How can this kind of situation be prevented?

Regards,
Mohan

First, I need to see a real-life example where this use case makes sense. A one-to-one table relationship sjpuld not sllow this. If you want to change the parent, then the child entity should have its own id.

Probably an exception is worth throwing. You should create a Jira issue and assign it to me. Post the Jira issue link here when you create it.

Hi @vlad, I have created JIRA issue for this.

https://hibernate.atlassian.net/browse/HHH-13228

Regards,
Mohan

Thanks. I created this Pull Request to log a message which tells you that the property is not going to be updated even if it was modified.

Awesome @vlad. Thanks a lot. Is this going to be included in next release?

Most likely since I don’t see why it would get rejected.