Johan
Johan

Reputation: 3819

Simplify JSON serialization in @ManyToOne relationship

I have a question about ORM mapping with Spring JPA.

Consider a simple class Person:

@Entity
public class Person {

    @Id
    @NotNull
    @Column(unique = true, updatable = false, name = "PERSON_ID")
    private long personId;

    @NotNull
    @Size(min = 1)
    private String name;

    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<Car> cars;

    public Person() {
    } 
    //continue....

and a simple class Car:

@Entity
public class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "CAR_ID")
    private long carId;

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PERSON_ID")
    private Person person;

    @NotNull
    @Size(min = 1)
    private String typeOfCar;

    public Car() {
    } 
    //continue....

Person has a OneToMany relationship with Car.

Recalling that carId is auto-generated, when I POST a new car at the moment I am forced to specify a full Person object (apart from the nullable list of cars):

{
  "person": {
    "personId": 200,
    "name": "Jack"
  },
  "typeOfCar": "Ferrari"
}

I would like to be able to POST a car object just like this:

{
  "person": 200,
  "typeOfCar": "Ferrari"
}

thus specifying only the personId (key of the Person entity).

I guess that I need the Person reference in Car to be serialized only as its key and not as the whole object.

How to achieve this?

So far, what I have tried are the following annotations @JsonIdentityReference and @JsonIdentityInfo on the Person reference in Car as follows:

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PERSON_ID")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "personId")
@JsonIdentityReference(alwaysAsId = true)
private Person person;

but when I POST the simplified JSON I am getting the following 404:

"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "JSON parse error: Unresolved forward references for: ; nested exception is com.fasterxml.jackson.databind.deser.UnresolvedForwardReference: Unresolved forward references for: \n at [Source: java.io.PushbackInputStream@25614608; line: 5, column: 1]Object id [2] (for myapp.ws.people.entity.Person) at [Source: java.io.PushbackInputStream@25614608; line: 2, column: 13].",

Upvotes: 0

Views: 1503

Answers (1)

TrafLaw
TrafLaw

Reputation: 318

I think one way to achieve it is to

  1. create a DTO class

    class CarDto {
    private long person;
    private String typeOfCar;
    }
    
  2. then in your service have 2 repositories. one for person and other for car.

    class PersonService {
    
      public void post(CarDto car) {
       Person person = personRepository.findByPersonId(car.getPerson());
       Car newCar = new Car();
       newCar.setPerson(person);
       newCar.setTypeOfCar(car.getTypeOfCar);
       carRepository.save(newCar);
      }
    
    }
    

Upvotes: 2

Related Questions