Веб-приложение My Spring позволяет пользователям обновлять записи «Сотрудник», изменять поля или добавлять новые записи «Телефон», связанные с этой записью «Сотрудник».Однако, когда запись «Сотрудник» отправляется на обновление после добавления новой записи «Телефон», возникает исключение ошибки SQL.
Проблема заключается в том, что внешний ключ «employee_id» в таблице «Телефон»таблица «Сотрудник» не задана в возможном операторе вставки SQL, переданном в базу данных.Однако в объекте сущности JPA «PhoneEntity», на который ссылается обновленный / объединенный объект «EmployeeEntity», свойство, связанное с полем базы данных employee_id
, не равно нулю, для него установлено значение «EmployeeEnity»: объект обновляется / объединяется.
Исходя из моего понимания JPA, наличие свойства сущности, связанного с полем базы данных, должно устанавливать его, когда оператор вставки для записи сущности передается в базу данных, но в этом случае это не вызываетэта ошибка.
Я попытался пройти через отладчик, и я убедился, что созданный объект PhoneEntity
является членом свойства EmployeeEntity
phones
и того же * 1011Свойство * 'employee
установлено для того же объекта EmployeeEntity
(с теми же идентификаторами объекта) в двунаправленном отношении.
Я также установил hibernate.show_sql=true
, чтобы увидеть отправляемую инструкцию SQLв базу данных и включает в себя оператор (с эллипсами, являющимися большим количеством полей):
Hibernate:
insert
into
phone
(id, employee_id, ...)
values
(?, ?, ...)
Это означает, что он вставляет новый phone
для нового PhoneEntity
объекта.
После попытки выполнить этот оператор вставки выдает ошибку SQL "Столбец 'employee_id' не может быть пустым".Однако, как я уже говорил ранее, я проверил с помощью отладчика, и свойство employee
действительно установлено на объект EmployeeEntity
.
Это упрощенный пример того, как выглядит мой код:
@Entity
@Table(name = "employee")
public class EmployeeEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@OneToMany(mappedBy="employee", cascade = {CascadeType.PERSIST})
private Set<PhoneEntity> phones = new HashSet<>();
...
}
@Entity
@Table(name = "phone")
public class PhoneEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@ManyToOne
@JoinColumn(name = "employee_id", nullable = false)
private EmployeeEntity employee;
...
}
С таблицами, структура которых создается с помощью следующих операторов SQL.
CREATE TABLE employee (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
...
);
CREATE TABLE phone (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
employee_id INT NOT NULL,
...
FOREIGN KEY(employee_id) REFERENCES employee(id)
);
И далее, когда он фактически отправляет обновления менеджеру сущностей для обновления базы данных.
public void update(EmployeeDomain employee) {
EmployeeEntity entity = employeeDomainToEntity.transform(employee)
getEntityManager().merge(entity);
}
Объекты EmployeeEntity
и PhoneEntity
создаются путем преобразования похожих объектов домена, которые в свою очередь были десериализованы из запроса http.Я бы включил больше этого раздела кода, но, как я уже упоминал, я уже подтвердил с помощью моего отладчика, что реальные объекты сущностей, отправляемые на слияние, уже находятся в форме, которую мы ожидали с phones
поля и employee
поля установлены правильно, поэтому конечные объекты должны быть правильными.