I am looking for a way to model a relation between two or more objects of the same class in Hibernate. For example: I want to create a situation where I want to model relations between persons. In the database, I have two tables:
Person:
- Id
- Name
Relation:
- Parent Id
- Child Id
I tried to model this in Hibernate as a Person have two ManyToMany relations (Getter/Setter annotations are Lombok):
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "persons")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id
@Column(name="name")
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "relations",
joinColumns = {@JoinColumn(name = "parent_id", nullable = false)},
inverseJoinColumns = {@JoinColumn(name = "child_id", nullable = false)}
)
private Set<Person> children = new HashSet<>();
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "relations",
joinColumns = {@JoinColumn(name = "child_id", nullable = false)},
inverseJoinColumns = {@JoinColumn(name = "parent_id", nullable = false)}
)
private Set<Person> parents = new HashSet<>();
}
This gave me the following problems:
- With fetch type "LAZY" Hibernate complains about not having a Session when calling person.getChildren() or person.getParents()
- With fetch type "EAGER" Hibernate returns null for the sets, which causes nullpointers when trying to add children or parents. The other thing I am worried about is that possible endless recursive eager fetching.
To get around this, I've tried to model the Relation as a class, so that I can use JPA queries in the PersonRepository to find Children and Parents without having to mess with the intricacies of ManyToMany :
public interface PersonRepository extends JpaRepository<Person, Long> {
@Query(
"select p from Person p join Relation r on p.id = r.childId where r.childId = :childId"
)
List<Person> findParents(Long childId);
}
This caused Hibernate to complain that Relation does not have an @Id field. I do not want to add that because the relation table in the database should model the relation, and not have an id of its own.
When trying to search online for similar structures in Hibernate I usually find classic many-to-many examples in the documentation and questions like this one where there is a relation between two different classes instead of a relation between two objects of the same class.
I'm looking for a way to model a relation between two or more objects of the same class in Hibernate. I want to be able to fetch relations lazily, or fetch them afterwards for performance reasons.
It would be nice if the relation table could have an extra field "type" which indicates the type of relation between Persons (child, parent, nephew, friend) so that there is room for new relation types without too much changes to database and code.