Hello! I study Java as a whole, Spring and Hibernate are only 2 months old, so please do not judge strictly. I am writing my project - RESTfull API application on Spring MVC using Hibernate as ORM. It is not clear how best to design an API with Hibernate in mind. What is the problem: Suppose there is a table in the DB - "Book" (Book):

public class Book { @Id @GeneratedValue private int bookId; private String name; @OneToMany(mappedBy = "Book") private List<Chapter> chapters; } 

and the table - "Chapter" (Chapter):

 public class Chapter { @Id @GeneratedValue @ManyToOne private int chapterId; private String name; @JoinColumn(name = "bookId") private Book book; } 

A record has been added to the table with books:

 { "id" : "1" "name" : "Alice in wonderland" } 

An entry has also been added to the table with chapters:

 { "id": "1", "name" : "Down the Rabbit Hole" } 

Question # 1: When writing a controller, I would like the GET chapter / 1 method to return JSON of the form:

 { "chapterId" : 1, "name" : "Down the Rabbit Hole", "bookId" : "1" } 

but now, to get a record from the database, I use the get () method:

 chapter = (Chapter) session.get( Chapter.class, chapterId ); 

which returns an object of the form:

 { "chapterId" : 1, "name": "Down the Rabbit Hole", "Book" : { "bookId" : "1", "name": "Alice in wonderland" } } 

How to make it so that when a Chapter object is received, an object with the properties of the chapter + book identifier (and not the entire Book object) is returned?

Question # 2: A similar question, but according to the POST method, chapter / new for saving a new chapter. I would like to simplify the REST API of my application - if someone wants to save a new chapter in the database, he will need to pass only 2 parameters when calling the POST method: 1. Chapter name. 2. Link to the ID of the book. Accordingly, when calling the POST / chapter / new method, I want to be given an object of the form:

 { "name" : "The Pool of Tears", "bookId" : "1" } 

But since the @Entity Chapter has a link to Book, you need to ask the user to transfer not just an identifier, but the entire object:

 { "name" : "The Pool of Tears", "Book" : { "bookId" : "1", "name" : "Alice in wonderland" } } 

What to do in this situation, so as not to ask to transfer the entire Book object from the client side, while allowing Hibernate to save the Chapter object in the database?

For myself, I decided that you can use intermediate objects - models, in order to fill them in the right format based on Entity from the database and then return them to the client (in the case of GET ). And vice versa for POST — upon receiving from the client part of the object, obtain a certain model, which will then be converted into the Entity format for saving to the database.

But such a solution seems to be a crutch. Please tell the best practices for solving such problems. Thanks in advance to all who responded!

    2 answers 2

    For your first and second questions, for the Chapter class, you need to add one field, for example bookId . The class should look like this:

     public class Chapter { @Id @GeneratedValue private int chapterId; private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "bookId") private Book book; @Column(name = "bookId", insertable = false, updatable = false) private int bookId; } 

    Note that the book and bookId fields have the bookId column name in the database, but the bookId field bookId used only for reading from the database, but it is not recorded and is not updated in the database by means of a hibernate.

    On the second question, you can use this field to transfer the book ID from the front, but when writing to the database, you still need to create a Book object and put it in the book field of the Chapter class.

    • Thanks for the answer! What you need! :) - vanhelsing124

    Question # 1: Try using the @JsonIgnore annotation from the Jackson Library

    • Try to write more detailed answers. Explain what is the basis of your statement? - Nicolas Chabanovsky
    • Thanks, @JsonIgnore also turned out to be superfluous when getting an object with a book using the GET / book / {id} method. - vanhelsing124