chrx
chrx

Reputation: 2518

Spring Data Rest and entities' IDs in relationships

I'm working on a Spring Data Rest based Spring Boot service whose data model is similar to the one in the tutorial: https://www.baeldung.com/spring-data-rest-relationships

(In defining the entities, I'm using Lombok annotations):

@Data
@NoArgsConstructor
@Entity
@Table(name = "cale")
public class Book {

    @Id
    @GeneratedValue
    private long id;

    @Column(nullable=false)
    private String title;

    @ManyToOne
    private Library library;

}


@Data
@NoArgsConstructor
@Entity
@Table(name = "library")
public class Library {


    @Id
    @GeneratedValue
    private long id;
    
    //...


}

invoking the endpoint /books I get the following json:

{
      "_embedded": {
        "books": [
          {
            "id": 22,
            "title": "The title of the book",
            "_links": {
              "self": {
                "href": "http://192.168.33.20:8080/books/22"
              },
              "book": {
                "href": "http://192.168.33.20:8080/books/22"
              },
              "library": {
                "href": "http://192.168.33.20:8080/books/22/library"
              }
            }
          },
          .
          .
          .

in HAL style, the only reference to the library linked to a given book is through an URL like http://192.168.33.20:8080/books/22/library

In order to get the id of the library associated to book 22, I have to perform a second GET call to the URL, which is inefficient in many cases.

Moreover, this makes it very hard to implement queries like "GET all books associated to the library whose id is 101".

Is there a way to let Spring Data Rest include also the id of the associated entity into the returned json? Something like:

{
      "_embedded": {
        "books": [
          {
            "id": 22,
            "title": "The title of the book",
            "library_id": 101, 
            "_links": {
            .
            .
            .
            }
          },
          .
          .

Upvotes: 0

Views: 1176

Answers (1)

Fabien
Fabien

Reputation: 376

You can create a projection and use it by default with an excerpt.

To define the projection :

@Projection(
  name = "customBook", 
  types = { Book.class }) 
public interface CustomBook {
 
    @Value("#{target.id}")
    long getId(); 
    
    String getTitle();
    
    @Value("#{target.getLibrary().getId()}")
    int getLibraryId();
}

And call :

http://192.168.33.20:8080/books/22?projection=customBook

To use this projection by default configure your repo :

@RepositoryRestResource(excerptProjection = CustomBook.class)
public interface BookRepository extends CrudRepository<Book, Long> {}

Upvotes: 1

Related Questions