Session.merge issue an "INSERT" while it should issue an "UPDATE" -- Is It The Expected Behaviour?

Hello

I am trying to persist an entity (let’s call it Container) which has a one-to-one relation with another entity (let’s call it Child)

the “Child” contains a unique String which is also its Hibernate @Id.

the “Container”, as it turns out, can be uniquely (and naturally) identified by its Child’s identifier.

Put another way, the Container’s primary key is also its foreign-key reference to its Child.

I’m trying to map this one-directional relation.

However, I am coming across a unique-constraint violation problem when I try to “update” the Container with an updated Child

Please Let me explain further; this is the parent (Container):

@Entity(name="Container")
class Container {
  @Id
  private String veryUniqueStringSameAsChild;

  @MapsId
  @OneToOne(cascade=CascadeType.ALL)
  private Child child;

  // Setters & Getters ...
}

This is the child (Child):

@Entity(name="Child")
class Child {
  @Id
  private String veryUniqueString;

  private int numberOfBestFriends;

  // Setters & Getters
}

Now, this is what I’m trying to do:


Container parent = new Container();
    Child child = new Child();
    child.setVeryUniqueString("somethingUnique5");
    child.setNumberOfFriends(1);
parent.setChild(child);

session.saveOrUpdate(parent);

// update the child without changing its @Id
parent = new Container();
    child = new Child();
     // same identifier as , only an updated numberOfBestFriends
    child.setVeryUniqueString("somethingUnique5");
    child.setNumberOfFriends(40);
parent.setChild(child);

session.saveOrUpdate(parent); // FAILS!

Is this an expected behaviour? Shouldn’t the Child actually set the Parent’s identifier before the merge (or saveOrUpdate)?

I can’t say for sure how it is supposed to work, though you can try to find something in the specification. My understanding is that you will have to set the veryUniqueStringSameAsChild on Container as well, although I understand this is odd. If you find a reference in the JPA spec that says this should work, please add a link to a JIRA issue for this improvement.

Thanks for the response! the website that you linked to (https://jakarta.ee/specifications/persistence/3.0/ ) is not accessible from my country (it has been filtered) so I can’t access it (not easily, at the very least); but your answer is most probably what I was after: I used to believe that when “save” or “merge” (etc.) get called, the @MapsId somehow magically “cascades” the child entity’s @Id to the parent. Actually when I explicitly set the @Id of the parent (something that I expected to be done automatically by Hib Almighty!) the problem just went away

Sorry to hear about the filtering. Not sure if the specification is published elsewhere though. Anyway, I didn’t dig into this too deeply, so I can’t say for sure how it is supposed to work per the specification. Either way, I think this might be a nice improvement to add to Hibernate, so you can create a JIRA ticket if you like: https://hibernate.atlassian.net/

Thanks (again) for responding and many apologies for replying so late. I would have much liked to submit a ticket via the URL you kindly provided, but almost all HTTPS websites out of my country (Iran) are now effectively inaccessible in my region (Bushehr) ever since the protests and crackdowns started last week. GMail is barely accessible through Tor (itself barely accessible) and it is my only opportunity to apologize for asking such trivial questions and to thank you and your team for all your efforts.