i have a Question about referencing ParentEntities from Child Entites ir If i have something like this:
Parent.java:
@Entity(name ="Parent") public class Parent { @Id @Generate..... @Column private int id; @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent") private Set<Child> children; simple ... getter and setter ... }
And the Child.java:
@Entity(name ="Child") public class Child{ @Id @Generate.... @Column private int id; @ManyToOne private Parent parent; ... simple getter an setter }
Following Tables are going to be created:
Parent: int id Child: int id int parent_id (foreign key: parent.id)
Ok, so far, everthings fine. But when it comes to using this Reference from Java, i would think, you can do something like this.
@Transactional public void test() { Parent parent = new Parent(); Child child = new Child(); Set<Child> children = new HashSet<Child>(); children.add(child); parent.setChildren(children); entityManager.persist(parent); }
which leads to this in Database:
Parent: id 100 Child id paren_id 101 100
But thats not the case, you have to explicity set the Parent to the Child (which, i would think, the framework could probably do by itself).
So whats really in the database is this:
Parent: id 100 Child id paren_id 101 (null)
cause i haven't set the Parent to the Child. So my Question:
Do I really have to do sth. like this?
Parent.java:
... setChildren(Set<Child> children) { for (Child child : children) { child.setParent.(this); } this.children = children; } ...
Edit:
According to the fast Replies i was able to solve this Problem by using the @JoinColumn on the Reference-Owning Entity. If we take the Example from above, i did sth. like this:
Parent.java:
@Entity(name ="Parent") public class Parent { @Id @Generate..... @Column private int id; @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name= "paren_id") private Set<Child> children; simple ... getter and setter ... }
And the Child.java:
@Entity(name ="Child") public class Child{ @Id @Generate.... @Column private int id; ... simple getter an setter }
Now if we do this:
@Transactional public void test() { Parent parent = new Parent(); Child child = new Child(); Set<Child> children = new HashSet<Child>(); children.add(child); parent.setChildren(children); entityManager.persist(parent); }
The Reference is correctly set by the Parent:
Parent: id 100 Child id paren_id 101 100
Do I really have to do sth. like this?
That is one strategy, yes.
On bi-directional relationships there is an "owning" and a "non-owning" side of the relationship. Because the owning side in your case is on Child
, you need to set the relationship there for it to be persisted. The owning side is usually determined by where you specify @JoinColumn
, but it doesn't look like you're using that annotation, so it's likely being inferred from the fact that you used mappedBy
in the Parent
annotation.
You can read a lot more about this here.
It still seems to be the case. In parent Entity
you can have something like
@PrePersist private void prePersist() { children.forEach( c -> c.setParent(this)); }
in order to avoid repeating code for setting child/parent relationship elsewhere in code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With