Problem z dodawaiem do bazy danych

0

`klasa nr 1:

@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
public class Branch {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long branchId;
    private String city;
    private String street;
    private int localNumber;
    private int flatNumber;
    @OneToMany(targetEntity = Car.class)
    @JoinColumn(name = "carId")
    private List<Car> availableCars;
    @OneToMany(targetEntity = Employee.class)
   @JoinColumn(name = "employeeId")
    private List<Employee> employees;

        public Branch(String city, String street, int localNumber, int flatNumber){
            this.city = city;
            this.street = street;
            this.localNumber = localNumber;
            this.flatNumber = flatNumber;
        }

klasa nr 2 :

@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
public class Car {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long carId;

    private Mark mark;

    private String model;

    private CarBody carBody;

    private int yearbook;

    private Color color;

    private int mileage;

    private Status status;

    private int loanAmountPerDay;

    @OneToOne(targetEntity = Branch.class)
    @JoinColumn(name = "branchId")
    private Branch Branch;

    public Car(Mark mark, String model, CarBody carBody, int yearbook, Color color,
               int mileage, Status status, int loanAmountPerDay) {
        this.mark = mark;
        this.model = model;
        this.carBody = carBody;
        this.yearbook = yearbook;
        this.color = color;
        this.mileage = mileage;
        this.status = status;
        this.loanAmountPerDay = loanAmountPerDay;

    }

metoda:

 @PostMapping("/addCars")
    public boolean addCar(@RequestParam("mark") Car.Mark mark,
                          @RequestParam("model") String model,
                          @RequestParam("carBody") Car.CarBody carBody,
                          @RequestParam("yearBook") int yearbook,
                          @RequestParam("color") Car.Color color,
                          @RequestParam("mileage") int mileage,
                          @RequestParam("status") Car.Status status,
                          @RequestParam("loanAmountPerDay") int loanAmountPerDay) {
        return carAppService.addCar(new Car(mark, model, carBody, yearbook, color, mileage, status, loanAmountPerDay));
    }

po probie dodania samochodu wyskakuje error 500 w swaggerze, a w konsoli :
Cannot add or update a child row: a foreign key constraint fails (car_rental.car, CONSTRAINT FK4rkn92jee4bmqmtankibn4aov FOREIGN KEY (car_id) REFERENCES branch (branch_id))

mam 3 branche stworzone i z tego co ja rozumiem to jest problem z przypisaniem id brancha do samochodu?
jak moge rozwiazac ten problem? z gory dzieki za odpowiedzi

ed: przed stworzeniem branchy bez problemu dodalem metoda 2 samochody

2

Sformatuj proszę tekst to primo. Po drugie zamiast tysiąca @RequestParam przyjmuj jakiś obiekt z tymi polami. Tyle adnotacji nie wygląda elegancko... :/

0

uczę się dopiero i znam jedynie taki sposób, jak i gdzie utworzyć taki obiekt?

1
Mateusz3991 napisał(a):

po probie dodania samochodu wyskakuje error 500 w swaggerze, a w konsoli :
Cannot add or update a child row: a foreign key constraint fails (car_rental.car, CONSTRAINT FK4rkn92jee4bmqmtankibn4aov FOREIGN KEY (car_id) REFERENCES branch (branch_id))

mam 3 branche stworzone i z tego co ja rozumiem to jest problem z przypisaniem id brancha do samochodu?
jak moge rozwiazac ten problem? z gory dzieki za odpowiedzi

ed: przed stworzeniem branchy bez problemu dodalem metoda 2 samochody

Po pierwsze nie dajesz kodu carAppService, nie wiemy co tam MOŻE być
Po drugie zakładasz nowy samochód nie podając branch.
Po trzecie relację masz jeden do jeden (na pewno tego chciałeś?) czyli teoretycznie nowy Car musi mieć nowy Branch

2

Namieszałeś trochę z relacjami z tego co widzę. Powinno być coś takiego:

<...>
... class Branch {
<...>
    @OneToMany(mappedBy = "branch")
    private List<Car> availableCars;
<...>
}

<...>
... class Car {
<...>
    @ManyToOne
    @JoinColumn(name = "branchId")
    private Branch branch;
<...>
}

Nie dawaj właściwości "targetEntity" w adnotacjach relacji, bo jest opcjonalna jeśli z typu pola wynika klasa encji. Nie ma sensu dublować informacji. Adnotację "JoinColumn" dajesz tylko w klasie, która jest właścielem relacji. Nie wiem jak masz utworzone tabele w bazie, ale upewnij się, że w kolumnie "branchId" tabeli "car" możesz wpisać "null" jeśli próbujesz zapisać "Car" bez przypisanego "Branch". Nie wiem też jak masz zaimplementowaną metodę "addCar" z "carAppService", bo może tam też masz coś jeszcze namieszane.

2

Zamiast takiej ilości parametrów w kontrolerze lepiej zrób @RequestBody.

0
pleome napisał(a):

Namieszałeś trochę z relacjami z tego co widzę. Powinno być coś takiego:

<...>
... class Branch {
<...>
    @OneToMany(mappedBy = "branch")
    private List<Car> availableCars;
<...>
}

<...>
... class Car {
<...>
    @ManyToOne
    @JoinColumn(name = "branchId")
    private Branch branch;
<...>
}

Nie dawaj właściwości "targetEntity" w adnotacjach relacji, bo jest opcjonalna jeśli z typu pola wynika klasa encji. Nie ma sensu dublować informacji. Adnotację "JoinColumn" dajesz tylko w klasie, która jest właścielem relacji. Nie wiem jak masz utworzone tabele w bazie, ale upewnij się, że w kolumnie "branchId" tabeli "car" możesz wpisać "null" jeśli próbujesz zapisać "Car" bez przypisanego "Branch". Nie wiem też jak masz zaimplementowaną metodę "addCar" z "carAppService", bo może tam też masz coś jeszcze namieszane.

public interface CarAppService {

boolean addCar(Car car);

List<Car> getAllCars();

Car getCarByMark(Car.Mark mark);

boolean deleteCarById(long carId);

Optional<Car> carReservationByCarId(long carId);

boolean addBranch(Branch branch);

boolean addEmployee(Employee employee);

}
w bazie danych wartosc domyslna brancha jest null, ale moge wybrac jednego z 3.
jak probowalem do Car od razu w swaggerze dodac Brancha to jako argument pojawial mi sie String Branch zamiast listy Branchy do wybrania(mimo,ze to podalem jako @requestparam)

ed: po poprawieniu relacji nadal to samo jest

0
AnyKtokolwiek napisał(a):
Mateusz3991 napisał(a):

po probie dodania samochodu wyskakuje error 500 w swaggerze, a w konsoli :
Cannot add or update a child row: a foreign key constraint fails (car_rental.car, CONSTRAINT FK4rkn92jee4bmqmtankibn4aov FOREIGN KEY (car_id) REFERENCES branch (branch_id))

mam 3 branche stworzone i z tego co ja rozumiem to jest problem z przypisaniem id brancha do samochodu?
jak moge rozwiazac ten problem? z gory dzieki za odpowiedzi

ed: przed stworzeniem branchy bez problemu dodalem metoda 2 samochody

Po pierwsze nie dajesz kodu carAppService, nie wiemy co tam MOŻE być
Po drugie zakładasz nowy samochód nie podając branch.
Po trzecie relację masz jeden do jeden (na pewno tego chciałeś?) czyli teoretycznie nowy Car musi mieć nowy Branch

poprawilem relacje i jest bez zmian
jak probowalem brancha dac jako @request param to w swaggerze pokazywalo mi go jako Stringa a nie liste Branchy

0

Dodaj relacje do branch podczas zapisu Car.
Branch b = new Branch(parametry);
Car c = new Car(..., b, ...);
poza tym wstaw najlepiej kod na git i udostępnij.

0
Korges napisał(a):

Dodaj relacje do branch podczas zapisu Car.
Branch b = new Branch(parametry);
Car c = new Car(..., b, ...);
poza tym wstaw najlepiej kod na git i udostępnij.

https://github.com/MateuszMichalik93/CarApp
nic na razie nie zmienialem

0

Jeszcze tip nie uzywaj @data na encjach bo kiedys zrobisz printline na tym i distaniesz stackoverflow

1

W klasie Car zrób tak:

@ManyToOne
@JoinColumn(name = "branchId")
private Branch branch;

W klasie Branch:

@OneToMany(mappedBy = "branch")
private List<Car> availableCars;

Masz w konfigu ustawione aby pokazywało Ci co hibernate wyprawia z twoimi klasami, warto na to spojrzeć. Tak w ogóle wg. mnie pozwalanie hajbernejtowi na tworzenie tabel nie jest dobrym pomysłem. Zainteresuj się flyway/liquibase. Zamiast @RequestParam walnij @RequestBody Car car (encja na twarz i pchasz). Puściłem pustego jsona i dostałem 400 więc po stronie serwera mappingi powinny być już git.

1

Zmień te mapowania relacji i wyczyść bazę. Niech hibernate jeszcze raz utworzy tabele. Obecne ustawienie ddl-auto na update nie usunie wcześniej utworzonych nadmiarowo kolumn czy tabel mapowań relacji.

0
Skoq napisał(a):

W klasie Car zrób tak:

@ManyToOne
@JoinColumn(name = "branchId")
private Branch branch;

W klasie Branch:

@OneToMany(mappedBy = "branch")
private List<Car> availableCars;

Masz w konfigu ustawione aby pokazywało Ci co hibernate wyprawia z twoimi klasami, warto na to spojrzeć. Tak w ogóle wg. mnie pozwalanie hajbernejtowi na tworzenie tabel nie jest dobrym pomysłem. Zainteresuj się flyway/liquibase. Zamiast @RequestParam walnij @RequestBody Car car (encja na twarz i pchasz). Puściłem pustego jsona i dostałem 400 więc po stronie serwera mappingi powinny być już git.

podalbys tresc calej metody? bo nie wiem np co w returnie zwrocic a zeby nie bylo zadnych niejasnoci dla mnie od razu prosze o cala metode

0
Mateusz3991 napisał(a):
Skoq napisał(a):

W klasie Car zrób tak:

@ManyToOne
@JoinColumn(name = "branchId")
private Branch branch;

W klasie Branch:

@OneToMany(mappedBy = "branch")
private List<Car> availableCars;

Masz w konfigu ustawione aby pokazywało Ci co hibernate wyprawia z twoimi klasami, warto na to spojrzeć. Tak w ogóle wg. mnie pozwalanie hajbernejtowi na tworzenie tabel nie jest dobrym pomysłem. Zainteresuj się flyway/liquibase. Zamiast @RequestParam walnij @RequestBody Car car (encja na twarz i pchasz). Puściłem pustego jsona i dostałem 400 więc po stronie serwera mappingi powinny być już git.

podalbys tresc calej metody? bo nie wiem np co w returnie zwrocic a zeby nie bylo zadnych niejasnoci dla mnie od razu prosze o cala metode

object references an unsaved transient instance - save the transient instance before flushing

2

tylko,ze Set<> unikalne samochody by zapisywał a przecież mogą się powtórzyć - Mateusz3991 38 minut temu

No nie.
Zawartość klasy Car jest taka, ze ewidentnie dotyczy to jednej sztuki (np ma mileage i year) - mniemam, że myślowo nastawiłeś się na typ (model) samochodu. Ja bym dodał numer rejestracyjny, żeby było jasne.

Jeśli myślisz inaczej (=model samochodu), klasę trzeba zmienić, ale w mojej wyobraźni koncepcja wypożyczenia i dostępności się nie trzyma kupy. I tak wypożycza się pojedynczą sztukę.

Oczywiście Set<> wymaga przemyślanej implementacji hashCode i equals, aby tą "pojedynczość" prawidłowo wychwycić
Natomiast List<> użyte w tym kontekście w JPA jest wybitnie ciężkie i nienaturalne, silnik JPA daje duży wysiłek aby zachować sortowanie, robi różne dziwne rzeczy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1