Home > Back-end >  How to create a 3 way bi-directional relationship with @JsonManagedReference and @JsonBackReference
How to create a 3 way bi-directional relationship with @JsonManagedReference and @JsonBackReference

Time:01-12

My entities are set up as such:

Client

    @Entity
    @Table(name = "client")
    public class Client {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        
        ...
    
        @OneToMany(mappedBy = "client")
        @JsonManagedReference
        private List<Project> projects;
    }

Project

    @Entity
    @Table(name = "project")
    public class Project {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        
        ...
    
        @ManyToOne(name= "client")
        @JsonBackReference
        private Client client;

        @OneToMany(mappedBy = "project")
        @JsonManagedReference
        private List<Listing> listings;
    }

Listing

@Entity
    @Table(name = "listing")
    public class Listing{
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        
        ...

        @ManyToOne(name= "project")
        @JsonBackReference
        private Project project;
    }

Currently, If I make a call to a specific client by ID then I will get the Client, their projects, and the listings for that project. This works as it should. However, when I make a call to the Project by ID I only get the listings of that project, I would also like to know WHICH Client OWNS that project. Similarly, when I call Listing by ID then I ONLY receive the listing with that ID, I would also like the PROJECT which OWNS that Listing as well as the CLIENT which owns it, is this possible to do? Thank you.

CodePudding user response:

I don't see anything wrong with what you have, looks like it should work.

However, even if it does work, I'd expect it to be somewhat inefficient, as it's going to do two separate selects, one for the project, and another for the client.

Probably best to do an explicit join, as in:

@Query("select p from Project p join fetch p.client where p.id = ?1")

This should result in a single query with a join.

Oh, and in your posted code, you have misspelled "client" as "cient"

CodePudding user response:

Note that:

@JsonManagedReference is the forward part of reference – the one that gets serialized normally. @JsonBackReference is the back part of reference – it will be omitted from serialization. The serialized Item object does not contain a reference to the Client object.

Use @JsonIdentityInfo

@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id")
public class Client

@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id")
public class Project

@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id")
public class Listing

More info here: https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion

  •  Tags:  
  • Related