Всякий раз, когда я отправляю данные формы на мой контроллер отдыха, и они переходят в мой класс 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)
);
Что значит уже существующая запись? Я проверил, и в моей БД их нет. А можно подробнее как это исправить?
Редактирование (плохо, я не прочитал трассировку полностью): существует ограничение внешнего ключа в таблице FOO, на которую ссылаются. Обычно на FK ссылаются из другой таблицы (обычно это ключ какой-то другой таблицы). У вас есть сценарии DDL для созданной вами таблицы?
Да, я покажу свой DDL.
Существует таблица под названием «Меню», которая содержит идентификатор поля. Это упоминается здесь FOREIGN KEY (ID) REFERENCES Menu (ID). Хотя я не вижу DDL для таблицы меню, я предполагаю, что он существует, и это причина, по которой вставка не удалась.
DDL не актуален по соображениям конфиденциальности, но в нем есть все, кроме реальных названий вещей. Это не сбой, потому что у меня там нет таблицы. Я сделал DDL, как вы его видите, чтобы задать вопрос. Я не хочу раскрывать код моего работодателя.




Вы пытаетесь вставить новую запись в таблицу FOO, например. INSERT INTO Foo, но согласно определению вашей таблицы у вас есть ссылка на существующую запись в таблице Foo2 (а таблица Foo2 имеет ссылку на существующую запись в таблице Foo3)...
Таким образом, вам придется сначала создать ссылочные записи в этих таблицах в следующем порядке:
ВАЖНАЯ ЗАМЕТКА: Проверьте реляционный дизайн ваших таблиц. Кажется, вы смешиваете 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 пригодным для использования.
Уже существует запись для основного, определенного в таблице. Отсюда ограничение ссылочной целостности. Вы можете обновить, вставить новую запись с другим ключом, чтобы она работала!