1

I have two model classes:

Car which has owner field:

import lombok.Data;

import javax.persistence.*;

@Entity
@Data
public class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String carBrand;
    private String modelOfCar;
    private String gearbox;
    private int yearProduction;
    private int mileage;
    private String status;
    @ManyToOne
    @JoinColumn(name = "owner_id")
    private Owner owner;
}

And Owner which has cars field

@Entity
@Data
public class Owner implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nameOfOwner;
    private String surnameOfOwner;
    @OneToMany(mappedBy = "owner")
   
    private List<Car> cars = new ArrayList<>()
            
    public void addCarToOwner(Car car) {
        cars.add(car);
    }
}

I tried to add some sample data to embedded h2 DB within this data:

    Car car1 = new Car();
    car1.setCarBrand("asd");
    car1.setModelOfCar("asd");
    car1.setGearbox("asd");
    car1.setYearProduction(22018);
    car1.setMileage(321000);
    car1.setStatus("Available");

    Car car2 = new Car();
    car2.setCarBrand("asd");
    car2.setModelOfCar("asd");
    car2.setGearbox("asd");
    car2.setYearProduction(2011);
    car2.setMileage(6801020);
    car2.setStatus("Available");

  Owner owner1 = new Owner();
    owner1.setNameOfOwner("asd");
    owner1.setSurnameOfOwner("asd");
    owner1.addCarToOwner(car1);

    Owner owner2 = new Owner();
    owner2.setNameOfOwner("asd");
    owner2.setSurnameOfOwner("asd");
    owner2.addCarToOwner(car2);

  carRepository.save(car1);
    carRepository.save(car2);
    ownersRepository.save(owner1);
    ownersRepository.save(owner2);

When I check state of owner repository with findAll() method I get owner and empty list of his cars. When I run findAll() for cars repository I have null for owner, because I did not set it, but how can I set it when owner needs cars, and car need owner?

owner repository

car repository

All this causes that when I try to fetch user with given ID I get an empty list of cars for him.

miksz1
  • 31
  • 1
  • 11
  • try implement a getCars method that returns the list of cars owned, and see if it returns the list of cars. It might just be that your array of cars is not getting serialized. – Oirampok Jan 17 '21 at 22:55
  • @rakeshpan still returns 0 result. But I guess car should not have set owner as null, too – miksz1 Jan 17 '21 at 22:57
  • your owning side of the one to many relationship is car, because its the one with the foreign key "owner_id", so try create a car, create an owner, make a method to set a car's owner and try creating the relationship through the car side. – Oirampok Jan 17 '21 at 23:01

1 Answers1

1

Looks like you're creating a bi-directional OneToMany between Owner and Car. In this case, you'll need to synchronize both sides of the association.

Your utility method addCarToOwner could do this very well:

@Data
@Entity
public class Owner implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nameOfOwner;
    private String surnameOfOwner;
    @OneToMany(mappedBy = "owner")
    private List<Car> cars = new ArrayList<>()
    
    public void addCarToOwner(Car car) {
        car.setOwner(this);
        this.cars.add(car);
    }
}

By setting the Owner to the Car, you synchronize both sides of the association.

Matheus
  • 3,058
  • 7
  • 16
  • 37
  • and i should save owner first instead of car? Because now I get stackoverflow on car field for owner – miksz1 Jan 17 '21 at 23:13
  • you're getting infinite recursion because you're trying to serialize car, which has a reference to owner, which has a reference to car, so on and so forth. You need to break the circular reference during serialization. For example you are serializing to json using Jackson you can use @JsonIgnore annotations to prevent the circular reference. – Oirampok Jan 17 '21 at 23:18
  • @rakeshpan but I want to show in JSON owner's cars – miksz1 Jan 17 '21 at 23:19
  • you only need to ignore one side, so do jsonignore on @ManyToOne @JoinColumn(name = "owner_id") private Owner owner; – Oirampok Jan 17 '21 at 23:24
  • @rakeshpan I mean yea, it is ignoring but while debugging I get stackoverflow so I assume it must be somehow resolved. – miksz1 Jan 17 '21 at 23:30
  • As @rakeshpan said, you are getting an infinite recursion. That's causing the StackOverflow error. You have some options to solve that. One is adding `@JsonIgnore` to the `Owner` attribute at the `Car` class. – Matheus Jan 17 '21 at 23:50
  • @MatheusCirillo json is fine, it looks good, but while debugging I see that stackoverflow occurs, which is not good? – miksz1 Jan 18 '21 at 07:54
  • That's the normal behavior. The infinite recursion occurs while debugging, because the field is not ignored by the debugger. I don't know a reliable way to prevent this, other than using a `@ManyToOne` only, and having it as a unidirectional association.What I mean is: don't put a `List` on the `Owner`, just put the `Owner` in the `Car` and have a `@ManyToOne` annotation. Just because you can use the `@OneToMany`, it doesn't mean this should be the default. In a lot of use cases, it's better (really) to use `@ManyToOne` only. – Matheus Jan 18 '21 at 13:32