Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update Parent reference when adding to @ManyToOne [duplicate]

Let's assume a simple 1 Father -> n Children entity relationship (getters/setters omitted):

@Entity
public class Father {

    @Id
    @GeneratedValue
    private Integer id;

    @OneToMany(mappedBy="father", cascade=CascadeType.ALL)
    private List<Child> children = new ArrayList<>();

    ...
}

@Entity
public class Child {
    @Id
    @GeneratedValue
    private Integer id;

    @ManyToOne(cascade=CascadeType.ALL)
    private Father father;

    ...
}

When now trying to update that relationship by simply adding a child to the father, it doesn't work, since Child.father does not get updated:

Child child = new Child();
// optionally persist child first, tried
father.getChildren().add(child);
...save father

I tried using different CascadeTypes, but nothing seems to work to automatically update the Child.father reference. I know that a traditional way would be to have an "addChild" method, but I would like the know if there is an automatic way to do so?

My configuration is Spring Boot + JPA (Hibernate) + H2, automatically creating to database. Interesting enough, I have found some blog postings that seem to do exactly what I do here, but for them it works, but not for me. Strange.

like image 605
Florian Schaetz Avatar asked Dec 04 '25 07:12

Florian Schaetz


1 Answers

Yes, but it's not intended. I only really explain it because it may explain what you've seen in those blog posts. You can make the @OneToMany the owning side of the relationship by removing mappedBy and adding @JoinColumn. However, this is primarily intended for the case where you don't have a back reference. If you keep the @ManyToOne then Hibernate will see two relationships which happen to share the same columns. As far as I know however, it should work.

I have seen one unjustified reference once that it could cause performance issues but I can't find that reference any longer so I don't know for certain. There will be two issues with it which kind of demonstrate the "this isn't really how you should do this" nature of the option:

  1. The parent field will not be updated until the transaction/session is closed and the child entity is reloaded from the database.
  2. If you later decide to implement 2nd-level caching it can change the logic of your code. This is because the child entity might not be reloaded from the database for some time and, until it is, the parent field will be null.

You could implement this yourself with dynamic proxies and reflection, although you would have to control the creation of entities through a DAO/Repository to ensure they got proxied.

In the end, I wouldn't personally recommend it. The older I get the more I feel that the less black magic there is in your application the better.

like image 95
Pace Avatar answered Dec 06 '25 20:12

Pace