I have 3 tables having a one-to-many relationship with one another:
I am creating the middle InBetween
entity with the linked side entities:
Parent parentInstance = new Parent();
InBetween inBetweenInstance = new InBetween(parentInstance); // Telling it about the parent
Child childInstance = new Child(inBetweenInstance); // Telling it about the InBetween
So effectively I told each Many-relationship
entity about its parent. But the parent One-relationship
entity does not know about the children.
I know with hibernate there is this bidirectional relations where the one entity knows about the other vice versa but here I have not set both.
When I am persisting the middle entity I want to insert all 3 at once:
dbService.saveInBetween(inBetweenInstance);
The dbService.saveInBetween
is using the InBetween
entity class that extends PanacheEntityBase
to persist it to the DB.
@Transactional
public void saveInBetween(InBetween inBetween) {
InBetween.persist(inBetween);
}
What is the problem
Upon retrieval of the InBetween
records, by calling the InBetween.listAll()
method, I get the Parent
entities back but not the Child
ren.
If I look in the database nothing was inserted into the child
table.
If I change the code to tell the InBetween
instance to also know about the Child
, thus so both know about one another it works:
Parent parentInstance = new Parent();
InBetween inBetweenInstance = new InBetween(parentInstance);
// Both the Child and InBetween instances know about each other now
Child childInstance = new Child(inBetweenInstance);
inBetweenInstance.setChildren(List.of(childInstance)); //Added this
dbService.saveInBetween(inBetweenInstance);
I did not tell the Parent
about the InBetween
instance but I do need to do the same for with the child
.
My question is why is the behaviour different and what is the correct approach in doing it?
I added a minimum code project to Github and my classes are listed below:
3 entity classes:
@Entity
@Getter
@NoArgsConstructor
public class Parent extends PanacheEntityBase {
@Id
@GeneratedValue
private Long id;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<InBetween> inBetweens;
}
@Entity
@Getter
@Setter
@NoArgsConstructor
public class InBetween extends PanacheEntityBase {
@Id
@GeneratedValue
private Long id;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "parent_id")
private Parent parent;
@OneToMany(mappedBy = "inBetween", cascade = CascadeType.ALL)
private List<Child> children;
public InBetween(Parent parent) {
this.parent = parent;
}
}
@Entity
@Getter
@NoArgsConstructor
public class Child extends PanacheEntityBase {
@Id
@GeneratedValue
private Long id;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "inBetween_id")
private InBetween inBetween;
public Child(InBetween inBetween) {
this.inBetween = inBetween;
}
}
With the DBService
class
@ApplicationScoped
public class DBService {
@Transactional
public void saveInBetween(InBetween inBetween) {
InBetween.persist(inBetween);
}
public List<InBetween> findAllInBetweens() {
return InBetween.listAll();
}
}