0

I have a product table

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Product extends AuditModel {

    @Id
    @SequenceGenerator(name="optimized-sequence",sequenceName = "seq_product")
    private Integer id;
    private String sku;
    private String description;
    @NotNull
    private String name;

    *** 
    ***
    ***   

    @ManyToOne(optional = true)
    @JoinColumn(name = "category_id")
    @OnDelete(action = OnDeleteAction.NO_ACTION)
    private Category category;

    @ManyToOne(optional = true)
    @JoinColumn(name = "manufacturer_id")
    @OnDelete(action = OnDeleteAction.NO_ACTION)
    private Manufacturer manufacturer;

    @OneToMany(mappedBy = "product")
    private List<OrderProduct> orderProducts;

}

And a CrudRepository

public interface ProductRepository extends PagingAndSortingRepository<Product, Integer> {

    Product findFirstBydescription(@Param("description")String description);

}

when i call the endpoint /products by default I get a list of all products like this

{
  "_embedded" : {
    "products" : [ {
      "createdAt" : "2019-11-15T08:56:23.393+0000",
      "updatedAt" : "2019-11-15T08:56:23.393+0000",
      "id" : 802,
      "sku" : null,
      "name" : " product 1",
      "description" : "description one",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/products/802"
        },
        "product" : {
          "href" : "http://localhost:8080/api/products/802{?projection}",
          "templated" : true
        },
        "manufacturer" : {
          "href" : "http://localhost:8080/api/products/802/manufacturer"
        },
        "orderProducts" : {
          "href" : "http://localhost:8080/api/products/802/orderProducts"
        },
        "category" : {
          "href" : "http://localhost:8080/api/products/802/category"
        }
      }
    }, .......

How can I get, calling the default endpoint /products, inside the json object product the related objects too (Catefory, Manufacturer...)?

Thanks

Mikfaina
  • 85
  • 1
  • 9

3 Answers3

0

If am I understand you correctly, you should use FetchType.EAGER strategy inside the @ManyToOne or @OneToOne annotations for fetching all related data from the database.

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id")
@OnDelete(action = OnDeleteAction.NO_ACTION)
private Category category;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "manufacturer_id")
@OnDelete(action = OnDeleteAction.NO_ACTION)
private Manufacturer manufacturer;

@OneToMany(mappedBy = "product", fetch = FetchType.EAGER)
private List<OrderProduct> orderProducts;
oguzhan00
  • 499
  • 8
  • 16
  • `Spring-jpa creates the query using the entity manager, and Hibernate will ignore the fetch mode if the query was built by the entity manager.` @oguzhan00 – Mikfaina Nov 15 '19 at 14:16
0

You may want to rewrite your query using FETCH JOIN:

@Query("SELECT p FROM Product p JOIN FETCH p.category JOIN FETCH p.manufacturer JOIN FETCH p.orderProducts WHERE p.description = :description")
Product findFirstByDescription(@Param("description") String description);

It will fetch Product's associations eagerly.

Note that in this case you should make your associations lazily fetched (i.e set fetch parameter of association annotations to EAGER).

jolice
  • 98
  • 1
  • 6
  • Sorry but is not that query. I want to get all related objecs in the default endponint /products that CrudRepository exposes by default – Mikfaina Nov 15 '19 at 14:33
0

It's not possible with Spring Data Rest

It's not very clear in your question, but from what I see, I assume you use Spring Data Rest to expose your data.

As said in this answer

Spring Data REST uses Spring HATEOAS to automatically expose resources for entities managed by Spring Data repositories and leverages hypermedia aspects to do pagination, link entities etc.

The thing is, one of the main concepts behind HATEOAS is the discovery mechanism. It means that with an HATEOAS API, you won't have the possibility to make a "Lazy exposition" of your resources, it's against the philosophy of HATEOAS.

That's why I think if you really want related objects, you should avoid Spring Data Rest, it won't fit your needs.

Instead, you can make your own controllers. You will lose the facility that Spring Data Rest provides, with the CRUD operations already implemented for each entity. But you will have more flexibility with your data, and will be able to expose data with entities related in your JSON response.

Xavier FRANCOIS
  • 652
  • 4
  • 15