Search code examples
jpaspring-data-jpamappingone-to-many

Why is there a loop in @OneToMany mapping?


I am trying to create a @OneToMany database using JPA. There is a object Flight and a object Passenger.

the code:

@Entity
@Table(name = "passengers")
public class Passenger {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    
    @Column(name = "name")
    private String name;
    
    @Column(name = "surname")
    private String surname;
    
    private String email;
    
    private String phoneNumber;
    
    private String birthDate;
    
    @ManyToOne(optional = false)
    @JoinColumn(name = "flight_id")
    private Flight flight;
    
    public Passenger() {
    }
    
    public Passenger(String name, String surname, String email, String phoneNumber, String birthDate, Flight flight) {
        super();
        this.name = name;
        this.surname = surname;
        this.email = email;
        this.phoneNumber = phoneNumber;
        this.birthDate = birthDate;
        this.flight = flight;
    }
@Entity
@Table(name = "flights")
public class Flight {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "flight_id")
    private long id;
    
    private String departure;
    
    private String destination;
    
    private String date;
    
    private int capacity;
    
    private float price;
    
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "flight", cascade = CascadeType.ALL)
    private Set<Passenger> passengers;
    
    public Flight() {
        
    }

    public Flight(String departure, String destination, String date, int capacity, float price) {
        super();
        this.departure = departure;
        this.destination = destination;
        this.date = date;
        this.capacity = capacity;
        this.price = price;
    }

this is how I add a new Passenger:

@PostMapping("/flights")
    public ResponseEntity<Object> updateFlight(@RequestBody Flight flight) {
        long id = flight.getId();
        Optional<Flight> flightOptional = flightRepository.findById(id);

        if (!flightOptional.isPresent())
            return ResponseEntity.notFound().build();

        int currentCapacity = flight.getCapacity();
        flight.setCapacity(currentCapacity - 1);

        for(Passenger passenger : flight.getPassengers()) {
            System.out.println(passenger.getName());
        } 

        this.flightRepository.save(flight);

        return ResponseEntity.noContent().build();
    }

Unfortunately, when I map the flights and passengers, I appear to have a never ending loop. Passengers have the details of the flight and passengers and again flight and then passengers, and so on.

Is there any way I can resolve it? Am I missing anything?


Solution

  • To avoid the cyclic problem Use @JsonManagedReference, @JsonBackReference as below.

    Add @JsonManagedReference on Parent class

    @JsonManagedReference
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "flight", c 
     ascadee = CascadeType.ALL)
    private Set<Passenger> passengers;
    

    Add @JsonBackReference on child class as below

    @JsonBackReference
    @ManyToOne(optional = false)
    @JoinColumn(name = "flight_id")
    private Flight flight;