Сбой при создании записи DAO в БД — Spring Boot

Всякий раз, когда я отправляю данные формы на мой контроллер отдыха, и они переходят в мой класс DAO, я получаю эту ошибку:

org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation


2019-06-29 20:27:20.730 ERROR 5000 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: StatementCallback;SQL [INSERT INTO Foo(name, typeOfPlan, email, website, phoneNum, username, password) VALUES('Test', '2 Year', '[email protected]', 'test.org', '123456789', 'Master', '1234');]; Referential integrity constraint violation: "CONSTRAINT_B3: PUBLIC.FOO FOREIGN KEY(ID) REFERENCES PUBLIC.Foo(ID) (33)"; SQL statement:
INSERT INTO Foo(name, typeOfPlan, email, website, phoneNum, username, password) VALUES('Test', '2 Year', '[email protected]', 'test.org', '123456789', 'Master', '1234'); [23506-199]; nested exception is org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation: "CONSTRAINT_B3: PUBLIC.Foo FOREIGN KEY(ID) REFERENCES PUBLIC.Foo(ID) (33)"; SQL statement:
INSERT INTO Foo(name, typeOfPlan, email, website, phoneNum, username, password) VALUES('Test', '2 Year', '[email protected]', 'test.org', '123456789', 'Master', '1234'); [23506-199]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:457)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:427)
    at org.h2.message.DbException.get(DbException.java:205)
    at org.h2.message.DbException.get(DbException.java:181)
    at org.h2.constraint.ConstraintReferential.checkRowOwnTable(ConstraintReferential.java:319)
    at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:261)
    at org.h2.table.Table.fireConstraints(Table.java:1020)
    at org.h2.table.Table.fireAfterRow(Table.java:1038)
    at org.h2.command.dml.Insert.insertRows(Insert.java:194)
    at org.h2.command.dml.Insert.update(Insert.java:132)
    at org.h2.command.CommandContainer.updatmmandContainer.java:133)
    at org.h2.command.Command.executeUpdate(Command.java:267)
    at org.h2.server.TcpServerThread.process(TcpServerThread.java:398)
    at org.h2.server.TcpServerThread.run(TcpServerThread.java:175)
    at java.lang.Thread.run(Thread.java:748)
] with root cause

org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation: "CONSTRAINT_B3: PUBLIC.Foo FOREIGN KEY(ID) REFERENCES PUBLIC.Foo(ID) (33)"; SQL statement:
INSERT INTO Foo(name, typeOfPlan, email, website, phoneNum, username, password) VALUES('Test', '2 Year', '[email protected]', 'test.org', '123456789', 'Master', '1234'); [23506-199]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:457) ~[h2-1.4.199.jar:1.4.199]
    at org.h2.engine.SessionRemote.done(SessionRemote.java:607) ~[h2-1.4.199.jar:1.4.199]
    at org.h2.command.CommandRemote.executeUpdate(CommandRemote.java:237) ~
....

Остальное бесполезно и для причины конфиденциальности не отображается. Я гарантировать вам, это все данные, которые вам нужны, и в них есть все вложенные исключения/ошибки.

ДАО

@Repository
public class SomeDAOImpl implements ISomeDAO {

    @Autowired
    private JdbcTemplate temp;

public void createRecord(Foo foo) {

        // SQL insert statement
        String sql = "INSERT INTO Foo(name, typeOfPlan, email, website, phoneNum, username, password) " +
                "VALUES(" + "\'" + foo.getName() + "\'" + ", " + "\'" + foo.getTypeOfPlan() + "\'" + ", " + "\'" + foo.getEmail() + "\'" + ", " +
                "\'" + foo.getWebsite() + "\'" + ", " + "\'" + foo.getPhoneNum() + "\'" + ", " + "\'" + foo.getUsername() + "\'" +
                ", " + "\'" + foo.getPassword() + "\'" + ");";

        // Updates the table with the new record
        // Error here
        temp.update(sql);
    }
}

ПОЖО

@JsonIgnoreProperties(ignoreUnknown = true)
public class Foo {

    private String name;
    private String typeOfPlan;
    private String email;
    private String website;
    private String phoneNum;
    private String username;
    private String password;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTypeOfPlan() {
        return typeOfPlan;
    }

    public void setTypeOfPlan(String typeOfPlan) {
        this.typeOfPlan= typeOfPlan;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getWebsite() {
        return website;
    }

    public void setWebsite(String website) {
        this.website = website;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Как это исправить и предотвратить это?

Обновлено:

Мой DDL для моих таблиц:

create table Foo3 (
    ID INT AUTO_INCREMENT,
    foo1 VARCHAR(30) NOT NULL,
    foo2 VARCHAR(10) NOT NULL,
    foo3 VARCHAR(50) NOT NULL,
    PRIMARY KEY(ID)
);

create table Foo2 (
    ID INT AUTO_INCREMENT,
    name VARCHAR(64) NOT NULL,
    PRIMARY KEY(ID),
    FOREIGN KEY (ID) REFERENCES Foo3(ID)
);

create table Foo (
    ID INT AUTO_INCREMENT,
    name VARCHAR(64) NOT NULL,
    typeOfPlan VARCHAR(30) NOT NULL,
    email VARCHAR(35) NOT NULL,
    website VARCHAR(40),
    phoneNum VARCHAR(35) NOT NULL,
    username VARCHAR(35) NOT NULL,
    password VARCHAR(35) NOT NULL,
    PRIMARY KEY(ID),
    FOREIGN KEY (ID) REFERENCES Foo2(ID)
);

Уже существует запись для основного, определенного в таблице. Отсюда ограничение ссылочной целостности. Вы можете обновить, вставить новую запись с другим ключом, чтобы она работала!

Ramachandran.A.G 30.06.2019 03:52

Что значит уже существующая запись? Я проверил, и в моей БД их нет. А можно подробнее как это исправить?

Compiler v2 30.06.2019 03:55

Редактирование (плохо, я не прочитал трассировку полностью): существует ограничение внешнего ключа в таблице FOO, на которую ссылаются. Обычно на FK ссылаются из другой таблицы (обычно это ключ какой-то другой таблицы). У вас есть сценарии DDL для созданной вами таблицы?

Ramachandran.A.G 30.06.2019 04:00

Да, я покажу свой DDL.

Compiler v2 30.06.2019 04:16

Существует таблица под названием «Меню», которая содержит идентификатор поля. Это упоминается здесь FOREIGN KEY (ID) REFERENCES Menu (ID). Хотя я не вижу DDL для таблицы меню, я предполагаю, что он существует, и это причина, по которой вставка не удалась.

Ramachandran.A.G 30.06.2019 04:26

DDL не актуален по соображениям конфиденциальности, но в нем есть все, кроме реальных названий вещей. Это не сбой, потому что у меня там нет таблицы. Я сделал DDL, как вы его видите, чтобы задать вопрос. Я не хочу раскрывать код моего работодателя.

Compiler v2 30.06.2019 04:29
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
578
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы пытаетесь вставить новую запись в таблицу FOO, например. INSERT INTO Foo, но согласно определению вашей таблицы у вас есть ссылка на существующую запись в таблице Foo2 (а таблица Foo2 имеет ссылку на существующую запись в таблице Foo3)... Таким образом, вам придется сначала создать ссылочные записи в этих таблицах в следующем порядке:

  1. Создайте запись в таблице Foo3
  2. Создайте запись в таблице Foo2, которая ссылается на запись Foo3.
  3. Создайте запись в таблице Foo, которая ссылается на запись Foo2.

ВАЖНАЯ ЗАМЕТКА: Проверьте реляционный дизайн ваших таблиц. Кажется, вы смешиваете PRIMARY KEY и FOREIGN KEY в одном и том же столбце таблицы под названием «ID». В идеале каждая таблица должна иметь свой собственный столбец первичного ключа и внешний ключ(и) в отдельном столбце(ах).

Ответ принят как подходящий

Исправление состоит в том, чтобы обновить мой DDL, я обнаружил, что сделал FOREIGN KEY неправильно.

Вот обновленная версия:

create table Foo3 (
    ID INT AUTO_INCREMENT PRIMARY KEY,
    foo1 VARCHAR(30) NOT NULL,
    foo2 VARCHAR(10) NOT NULL,
    foo3 VARCHAR(50) NOT NULL
);

create table Foo2 (
    ID INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(64) NOT NULL,
    Foo3_ID INT NULL,
    CONSTRAINT FK_FOO2_FOO3_ID FOREIGN KEY(FOO3_ID) REFERENCES FOO3(ID)
);

create table Foo (
    ID INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(64) NOT NULL,
    typeOfPlan VARCHAR(30) NOT NULL,
    email VARCHAR(35) NOT NULL,
    website VARCHAR(40),
    phoneNum VARCHAR(35) NOT NULL,
    username VARCHAR(35) NOT NULL,
    password VARCHAR(35) NOT NULL,
    Foo2_ID INT NULL,
    CONSTRAINT FK_FOO_FOO2_ID FOREIGN KEY(FOO2_ID) REFERENCES Foo2(ID)
);

Мне нужно было добавить свойство NULL, чтобы разрешить пустые ссылки FK, и мне пришлось добавить CONSTRAINT, чтобы сделать FOREIGN KEY пригодным для использования.

Другие вопросы по теме