Как бороться с дочерними объектами с уникальными атрибутами в JPA + Hibernate + Spring? - PullRequest
0 голосов
/ 04 мая 2020

Сохранение связи «многие к одному» работает только в первый раз. Как сохранить отца с добавленным дочерним элементом, если дочерние записи уже существуют, и предотвратить сообщение об ошибке «Уникальный индекс или первичный ключ нарушен»?

Примечание: атрибут name уникален!

Основная программа.

// This works 
            Car car1 = new Car();
            Car car2 = new Car();
            Car car3 = new Car();

            Model model1 = new Model();
            Model model2 = new Model();

            model1.setName("911");
            model2.setName("Vito");

            car1.setLicense("S-TU-123");
            car2.setLicense("S-GH-124");
            car3.setLicense("S-BN-123");

            car1.setModel(model1);
            car2.setModel(model2);
            car3.setModel(model1);

            carRepository.saveAll(Arrays.asList(car1, car2, car3));

            //// wont work because of "Unique index or primary key violated"

            Car car4 = new Car();
            Model model4 = new Model();

            car4.setModel(model4);

            model4.setName("911"); // <== exists in database already
            car4.setLicense("L-QQ-001");

            carService.save(car4);

код модели:

import javax.persistence.*;
import lombok.*;

@Entity
@Table(name = "cars")
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
public class Car {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id;

    @Column
    private String license;

    @EqualsAndHashCode.Exclude
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "model_id", referencedColumnName = "id")
    private Model model;

    public void setModel(Model model) {
        this.model = model;
        model.getCars().add(this);
    }

    public void removeModel(Model model) {
        this.model = model;
        model.getCars().add(null);
    }
}

код автомобиля:

import javax.persistence.*;
import lombok.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "models")
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
public class Model {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id;

    @Column(unique = true)
    private String name;

    @EqualsAndHashCode.Exclude
    @OneToMany(mappedBy = "model", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<Car> cars = new HashSet<>();

    public void setCars(Set<Car> cars) {
        this.cars = cars;
        for (Car car : cars) {
            car.setModel(this);
        }
    }
}

хранилище автомобилей:

public interface CarRepository extends JpaRepository<Car, Long> {
}

хранилище моделей:

public interface ModelRepository extends JpaRepository<Model, Long> {
    Optional<Model> findByLicense(String license);
}
...