Hibernate Many-To-Many ссылка на себя. Проблема с добавлением в h2 БД. org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException

152
21 мая 2022, 16:30

У меня есть Entity:

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "planets")
public class Planet extends BaseEntity {
    @ManyToMany(cascade={CascadeType.ALL})
    @JoinTable(name="related_planets",
            joinColumns={@JoinColumn(name="closing_id")},
            inverseJoinColumns={@JoinColumn(name="opening_id")})
    private Set<Planet> openingPlanets = new HashSet<>();
    @ManyToMany(cascade={CascadeType.ALL})
    @JoinTable(name="related_planets",
            joinColumns={@JoinColumn(name="opening_id")},
            inverseJoinColumns={@JoinColumn(name="closing_id")})
    private Set<Planet> closingPlanets = new HashSet<>();
}

Код популяции БД:

Planet moon = new Planet();
Planet earth = new Planet();
Planet mars = new Planet();
mars.getOpeningPlanets().add(moon);
mars.getClosingPlanets().add(earth);
planetSDJPAService.save(mars);
planetSDJPAService.save(earth);
planetSDJPAService.save(moon);

В БД, в таблицу related_planets попадают правильные значения, но при этом

moon.getClosingPlanets()

по-прежнему возвращает пустое множество. Покопавшись в StackOverflow я понял, что это не происходит автоматически, а надо добавлять самому. Я добавил следующие методы для добавления в множества:

public void putOpeningPlanet(Planet openingPlanet) {
    openingPlanet.closingPlanets.add(this);
    this.openingPlanets.add(openingPlanet);
}
public void putClosingPlanet(Planet closingPlanet) {
    closingPlanet.openingPlanets.add(this);
    this.closingPlanets.add(closingPlanet);
}

Код для популяции стал следующим:

Planet moon = new Planet();
Planet earth = new Planet();
Planet mars = new Planet();
mars.putOpeningPlanet(moon);
mars.putClosingPlanet(earth);
planetSDJPAService.save(mars);
planetSDJPAService.save(earth);
planetSDJPAService.save(moon);

Но теперь я получаю ошибку из-за вставки не уникальных значений в related_planets:

Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.PRIMARY_KEY_1 ON PUBLIC.RELATED_PLANETS(OPENING_ID, CLOSING_ID) VALUES 1"; SQL statement: insert into related_planets (closing_id, opening_id) values (?, ?) [23505-200]

Как можно решить эту проблему?

Answer 1

Вы пытаетесь вставить одну запись дважды. Обратите внимание на SQL, который получается:

mars.putOpeningPlanet(moon); // допустим moon ID = 1, mars ID = 3
public void putOpeningPlanet(Planet openingPlanet) {
    openingPlanet.closingPlanets.add(this); //INSERT INTO related_planets(opening_id, closing_id) VALUES (1, 3);
    this.openingPlanets.add(openingPlanet); //INSERT INTO related_planets(opening_id, closing_id) VALUES (1, 3);
}
Answer 2

Проблема исчезла после замены аннотаций в Entity. Код ниже:

@ManyToMany(cascade={CascadeType.ALL})
@JoinTable(name="related_planets",
        joinColumns={@JoinColumn(name="closing_id")},
        inverseJoinColumns={@JoinColumn(name="opening_id")})
private Set<Planet> openingPlanets = new HashSet<>();
@ManyToMany(cascade = {CascadeType.ALL}, mappedBy = "openingPlanets")
private Set<Planet> closingPlanets = new HashSet<>();
READ ALSO
Почему теряются все ZipEntry после первого?

Почему теряются все ZipEntry после первого?

У меня есть SequenceInputStream, в котором находятся 3 FileInputStream-аКаждый из них открыт для zip папки, в которой лежит текстовый файл

230
Установить анимацию на программный dismiss BottomSheetDialogFragment&#39;а

Установить анимацию на программный dismiss BottomSheetDialogFragment'а

Господа, вопрос скорее всего простой, но при гуглении кидает на "кастомные анимации"Есть BottomSheetDialogFragment который открывается и скрывается...

171
Зачем нужен JNDI, если есть Spring IoC container (dependency lookup)?

Зачем нужен JNDI, если есть Spring IoC container (dependency lookup)?

Пишут, что JNDI нужен для того, чтобы мы могли из Java-кода получить Java-объект из некоторой "Регистратуры" объектов по имени объекта, привязанного...

234
Java: Jlabel не отображается

Java: Jlabel не отображается

Изучаю библиотеку java awt и java swing(И вообще всю Java) и столкнулся с проблемой JLabel не отображается на экранеВроде все процессы инициализированы

187