@ManyToOne and @OneToMany adding and retrieving problem in springboot

71 views Asked by At

I am encountering a problem in my Spring Boot JPA application related to relationships between the Owner and Car entities. The issue arises when attempting to associate a new Car with an existing Owner or when adding a new Owner with a set of Cars. While the owner and cars are added successfully to the database, the owner_id in the Car table is set to null and when trying to retrieve an owner I get no response.

Could anyone help to find a solution : My objective is adding owner with sets of cars, retrieving owners with their cars and while inserting a car with an existing owner it will be retrieved also.

these are my classes and json payloads:

Car.java class

@Entity
@Table(name="Car")
@Data
public class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "car_id")
    private Long id;

    @Column(name = "name")
    private String car_name;

    @Column(name = "model")
    private String Lmodel;

    @Column(name = "firstY")
    private String firsty;

    @ManyToOne()
    @JoinColumn(name="owner_id", referencedColumnName = "owner_id")        
    private Owner owner;

Owner.java Class

@Entity
@Table(name="Owner")
@Data
public class Owner {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "owner_id", nullable = false)
    private Long id;

    @Column(name = "first_name")
    private String first_name;

    @Column(name = "last_name")
    private String last_name;

    @Column(name = "address")
    private String address;

    @OneToMany(targetEntity = Car.class, mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Car> car;

}

Main Controller

package com.example.product.controllers;

import com.example.product.model.Car;
import com.example.product.model.CarService;
import com.example.product.model.Owner;
import com.example.product.model.OwnerService;
import jakarta.transaction.Transactional;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@AllArgsConstructor
@RestController
public class MainController {

    @Autowired
    private CarService carService;

    @Autowired
    private  OwnerService ownerService;

    @Transactional
    @DeleteMapping(value = "/Owner/{id}")
    public void deleteOwner(@PathVariable Long id){
        ownerService.deleteOwnerById(id);
    }

    @PostMapping(value = "/Owner")
    public void addOwner(@RequestBody Owner owner){
        ownerService.addOwner(owner);
    }

    @GetMapping(value = "/Owner/{id}")
    public Owner getOwner(@PathVariable Long id){
        return  ownerService.findOwnerById(id);
    }

    @PutMapping(value = "/Owner")
    public void updateOwner(Long id, String firstName, String lastName, String email, Car car){
        ownerService.updateOwner(id,firstName,lastName,email,car);
    }

    @GetMapping(value = "/Owners")
    public List<Owner> getAllOwners(){ return ownerService.getAllOwners();}

    @Transactional
    @DeleteMapping (value = "/Car/{id}")
    public void deleteCar(@PathVariable Long id){
        carService.deleteCarById(id);
    }

    @PostMapping(value = "/Car")
    @ResponseStatus(HttpStatus.CREATED)
    public void addCar(@RequestBody  Car car){
        carService.addCar(car);
    }

    @GetMapping(value = "/Car/{id}")
    public Car getCar(@PathVariable Long id){
        return  carService.getCarById(id);
    }

    @PutMapping(value = "/Car")
    public void updateCar (Long id,String firsty,String name,String model){
        carService.updateCarById(firsty,name,model,id);
    }

    @GetMapping(value="/Cars")
    public List<Car> getAllCars(){
        return carService.getAllCars();
    }
}

Json payload to add a car into the database

{
"car_name": "Toyota",
"lmodel": "Camry",
"firsty": "2023",
"owner": {
  "id": 1
    }
}

Json payload to add an owner into the database

{
  "first_name": "John",
  "last_name": "Doe",
    "address": "123 Main Street",
  "car": [
    {
      "car_name": "BMW",
      "lmodel": "Model 3",
      "firsty": "2022"            },
    {
      "car_name": "Mercedes",
      "lmodel": "C-Class",
      "firsty": "2021"      
        }
  ]
}
3

There are 3 answers

0
Kendy Alvarado On

It appears that the reference to the Owner class in the Car class may not be correct.

Please consider using the code below for proper referencing.

public class Owner {
  @OneToMany(mappedBy="owner", cascade = CascadeType.ALL, orphanRemoval = true)
  private List<Car> car;
}

public class Car {
  @ManyToOne
  @JoinColumn(name="owner_id", nullable=false)
  private Owner owner;
}
0
Karsten On
  1. With a bidirectional OneToMany/ManyToOne relationship you have to set the parent object (owner in your case) within the child objects (Car) or you'll get orphaned objects in your database. It's not sufficient to put the child objects into the list of the parent.
  2. Remove the referencedColumnName from the relationship in Car and the targetEntity in Owner.

For getting a reference to the foreign object you may consider to use JpaRepository.getReferenceById in Spring Data JPA 3.1+.

0
Murat Yıldız On

Try this approach:

@Entity
@Table(name="car")
@Data
public class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // other fields

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "owner_id", referencedColumnName = "id", nullable = false)
    private Owner owner;
}

@Entity
@Table(name="owner")
@Data
public class Owner {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;

    private String lastName;

    // other fields

    @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Car> cars = new HashSet<>();

    public void addCar(Car car) {
        cars.add(car);
        car.setUser(this);
    }

    public void removeCar(Car car) {
        cars.remove(car);
        car.setUser(null);
    }
}