Я пытаюсь сохранить объект TaskCard
Сервис TaskCard:
public TaskCard create(TaskCardCreateData taskCardCreateData) {
var creator = authenticatedUserService.getAuthenticatedUser();
var taskCard = new TaskCard(
taskCardCreateData.title(),
taskCardCreateData.description(),
taskCardCreateData.dueDate(),
creator,
taskCardCreateData.priority()
);
return taskCardRepository.save(taskCard);
}
Контроллер:
@PostMapping @Transactional public ResponseEntity createTaskCard(@RequestBody @Valid TaskCardCreateData taskCardCreateData, UriComponentsBuilder uriComponentsBuilder){
var taskCard = taskCardService.create(taskCardCreateData);
var uri = uriComponentsBuilder.path("/taskcard/{id}").buildAndExpand(taskCard.getId()).toUri();
return ResponseEntity.created(uri).body(new TaskCardDetailData(taskCard));
}
Аутентифицированный сервис получения пользователей:
public User getAuthenticatedUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return (User) authentication.getPrincipal();
}
Пользователь сущности:
@Table(name = "users")
@Entity(name = "User")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
private String login;
private String password;
@OneToMany(mappedBy = "creator")
private Set<TaskCard> taskCards;
...
}
Карта задач сущности:
@Table(name = "taskcards") @Entity(name = "TaskCard") public class TaskCard {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String description;
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
private LocalDateTime dueDate;
@ManyToOne
@JoinColumn(name = "creator_id")
private User creator;
public TaskCard() {
}
public TaskCard(String title, String description, LocalDateTime dueDate, User creator, String priority) {
this.title = title;
this.description = description;
this.createdDate = LocalDateTime.now();
this.dueDate = dueDate;
this.creator = creator;
this.priority = priority;
this.status = TaskCardStatus.BACKLOG;
this.active = true;
}...`
Ошибка:
Hibernate: insert into taskcards (active, created_date, creator_id, description, due_date, priority, status, title, updated_date) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
2024-08-27T22:44:36.744-04:00 WARN 35454 --- \[todolu\] \[nio-8080-exec-1\] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1452, SQLState: 23000 2024-08-27T22:44:36.744-04:00 ERROR 35454 --- \[todolu\] \[nio-8080-exec-1\] o.h.engine.jdbc.spi.SqlExceptionHelper : Cannot add or update a child row: a foreign key constraint fails (todolu.taskcards, CONSTRAINT fk_taskcards_users FOREIGN KEY (creator_id) REFERENCES users (id) ON DELETE CASCADE) 2024-08-27T22:44:36.756-04:00 ERROR 35454 --- \[todolu\] \[nio-8080-exec-1\] o.a.c.c.C.\[.\[.\[/\].\[dispatcherServlet\] : Servlet.service() for servlet \[dispatcherServlet\] in context with path \[\] threw exception \[Request processing failed: org.springframework.dao.DataIntegrityViolationException: could not execute statement \[Cannot add or update a child row: a foreign key constraint fails (todolu.taskcards, CONSTRAINT fk_taskcards_users FOREIGN KEY (creator_id) REFERENCES users (id\`) ON DELETE CASCADE)\] \[insert into taskcards (active,created_date,creator_id,description,due_date,priority,status,title,updated_date) values (?,?,?,?,?,?,?,?,?)\]; SQL \[insert into taskcards (active,created_date,creator_id,description,due_date,priority,status,title,updated_date) values (?,?,?,?,?,?,?,?,?)\]; constraint \[null\]\] with root cause
java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (todolu.taskcards, CONSTRAINT fk_taskcards_users FOREIGN KEY (creator_id) REFERENCES users (id) ON DELETE CASCADE)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:118) \~\[mysql-connector-j-8.3.0.jar:8.3.0\]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) \~\[mysql-connector-j-8.3.0.jar:8.3.0\]
в базе данных все происходит нормально, успех при вставке карт задач с действительными пользователями UUID и ошибка при вставке недействительных карт задач
Я уже пытался создать экземпляр и установить объект карты задач традиционным способом, не используя созданный собственный конструктор.
Печать переменных
пример обслуживания этой печати:
public TaskCard create(TaskCardCreateData taskCardCreateData) {
var creator = authenticatedUserService.getAuthenticatedUser();
System.out.println("CREATOR");
var teste = creator.toString();
System.out.println(teste);
var taskCard = new TaskCard(
taskCardCreateData.title(),
taskCardCreateData.description(),
taskCardCreateData.dueDate(),
creator,
taskCardCreateData.priority()
);
System.out.println("TASKCARD CREATOR");
var testedois = taskCard.getCreator().toString();
System.out.println(testedois);
return taskCardRepository.save(taskCard);
}
CREATOR User{id=66386333-6465-3364-2d31-6665612d3464, login='luiz.jolo', password='$2a$12$FohqZ/qawqsrlhmFH0zoE.SoviWTjKN18Qyi6EnBcfZjm5qLbBn9y'} TASKCARD CREATOR User{id=66386333-6465-3364-2d31-6665612d3464, login='luiz.jolo', password='$2a$12$FohqZ/qawqsrlhmFH0zoE.SoviWTjKN18Qyi6EnBcfZjm5qLbBn9y'}
Тот же объект!
@talex Автор упомянул в описании, когда он пытается распечатать объект-создатель, ответ => User{id=66386333-6465-3364-2d31-6665612d3464, login='luiz.jolo', пароль='$2a$12$FohqZ /qawqsrlhmFH0zoE.SoviWTjKN18Qyi6EnBcfZjm5qLbBn9y'}
Этот объект получен из БД или создан каким-то другим способом?
Можете ли вы рассказать об этом подробнее: «успех при вставке карт задач с действительными пользователями UUID и ошибка при вставке недействительных карт задач»?
@talex На основе кода, упомянутого в описании, он извлекает данные пользователя из уже загруженного объекта аутентификации, хранящегося в памяти, а не из БД.
@SamPaulIsaac Похоже, мне нужны новые очки :) но это объясняет проблему. Нам нужно увидеть, кто установил принципал в объекте Authentication
. Похоже, это исходит не от БД.
@talex «Нам нужно посмотреть, кто установил принципала в объекте аутентификации». - Я согласен.
Кроме того, нам необходимо ПРОВЕРИТЬ, что таблица пользователей содержит пользователя с идентификатором, который соответствует идентификатору Creator_id, вставленному в таблицу Taskcards.
Я согласен, что, скорее всего, пользователь не был сохранен в базе данных до того, как попытался сохранить карточку задачи, поэтому ограничение не может быть удовлетворено. Вы можете попробовать каскадное сохранение, но если вы не убедитесь, что каждый пользователь имеет уникальный идентификатор, вы рискуете получить несколько объектов для одного и того же пользователя. Следовательно, лучше убедиться, что пользователь хранится в БД, и получить правильный идентификатор при загрузке принципала.
Упомянутый случай успеха и ошибки относится к добавлению «карт задач» непосредственно с кодом SQL в базу данных. Если я попытаюсь добавить «карту задач» с несуществующим или недействительным UUID, банк не разрешит это. В базе данных есть пользователь с UUID, упомянутым в коде, поскольку он нормально аутентифицируется и получает ключ JWT, и поэтому я могу зафиксировать это в «getAuthenticatedUser».
Проблема решена! Это моя неудача в момент создания таблиц базы данных с пролетными миграциями, это тип идентификатора, я использовал VARCHAR (36), а теперь меняю на BINARY (16), пользовательскую таблицу и карты задач, и проблема решена. Я должен был опубликовать схему.
Что
authenticatedUserService.getAuthenticatedUser()
возвращает?