Home > Enterprise >  How to implement a JPA birectional relation for entities that works from both sides
How to implement a JPA birectional relation for entities that works from both sides

Time:09-29

Another question regarding bi-directional relationship with JPA entities:

Suppose I have the following two classes:

@Entity
public class Product
{
    @Id
    private Long productID;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JsonManagedReference
    @JoinColumn(name = "fk_supplier")
    private Supplier supplier;

    private String description;

    public Supplier getSupplier()
    {
        return supplier;
    }
}

And

@Entity
public class Supplier
{
    @Id
    private Long supplierID;

    @OneToMany(mappedBy = "supplier")
    @JsonBackReference
    private Set<Product> products = new HashSet<>();

    private String name;

    public Set<Product> getProducts()
    {
        return products;
    }
}

With those definitions, I get the results back that I want if I query for a product. For example like this:

{
    "productID": 1,
    "supplier": {
        "supplierID": 1,
        "name": "Acer"
    },
    "description": "Gaming chair"
}

But if I do it the other way round, thus querying a supplier, I only get this back:

{
    "supplierID": 1,
    "name": "Acer"
}

Here I am missing the products.

How can this be achieved?

CodePudding user response:

OneToMany is inherently lazy so if you want to load Supplier and all products you need to eagerly fetch the products

@OneToMany(fetch = FetchType.EAGER)

// or

@Query("select s from Supplier s left join fetch s.products  where s.supplierID = 1)

Also as you have a circular dependency between supplier and product you have used @JsonBackReference on the products collection which will prevent the products being serialised to json, hence your response

If you want to return Supplier with list of products or a product with the supplier and prevent circular dependency issues remove @JsonBackReference and @JsonManagedReference reference and use @JsonIgnoreProperties instead
    @JsonIgnoreProperties("products")
    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "fk_supplier")
    private Supplier supplier;

    @JsonIgnoreProperties("supplier")
    @OneToMany(mappedBy = "supplier", fetch = FetchType.EAGER)
    private Set<Product> products = new HashSet<>();
  • Related