Привет, я делаю заявку на рецепт. У одного пользователя может быть много рецептов, и тогда он может удалить свой рецепт. Я храню дату в базе данных. У пользователя есть список рецептов в одном из полей базы данных. Я не знаю, что делать, чтобы удалить рецепт из этого списка. Я удаляю рецепт в базе данных, но он все еще находится в списке в пользовательском поле, поэтому мы все еще можем получить доступ к этому рецепту. Я использую JpaResporitory. Там я даю часть своего кода. Не могли бы вы мне помочь, пожалуйста ?
public ResponseEntity<String> deleteRecipeById(long id, @AuthenticationPrincipal UserDetails details) {//toDo
Recipe currentRecipe = getRecipeById(id);
User currentUser = userRepository.findByEmail(details.getUsername())
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
if(currentRecipe.getUser().equals(currentUser) ){
currentUser.deleteFromUserList(currentRecipe);
recipeRepository.delete(currentRecipe);
// AND WHAT HERE ?
return ResponseEntity.status(HttpStatus.OK).build();
}
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
@Entity
@Getter
@Setter
@RequiredArgsConstructor
public class Recipe {
...
@JsonIgnore
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
}
@Entity
@Table(name = "users")
@Getter
@Setter
@RequiredArgsConstructor
class User {
...
@JsonIgnore
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL,orphanRemoval = true , fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
@ToString.Exclude
@Column(name = "recipes")
private List<Recipe> recipes = new ArrayList<>();
} THERE IS THAT LIST THAT I CAN'T CHANGE AND NEED THIS TO DELETE RECIPE
вот как я сохраняю рецепт
public Long create(Recipe recipe, UserDetails details) {
User currentUser = userRepository.findByEmail(details.getUsername())
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
recipe.setUser(currentUser);
currentUser.getRecipes()
.add(recipe);
userRepository.save(currentUser);
return userRepository.findByEmail(details.getUsername())
.orElseThrow(() -> new UsernameNotFoundException("User not found"))
.getRecipes()
.get(userRepository.findByEmail(details.getUsername())
.orElseThrow(() -> new UsernameNotFoundException("User not found"))
.getRecipes()
.size() - 1)
.getId();
}
Я попытался погуглить, что прочитал статью о jpa, но до сих пор не знаю, что мне делать.
Где именно вы видите, что receipe
не удаляется от пользователя
public void deleteFromUserList (рецепт рецепта) { recipes.remove (рецепт); }
@GetMapping("/api/recipe/{id}") public ResponseEntity<Recipe> getRecipes(@PathVariable Long id) { return ResponseEntity.ok(recipeService.getRecipeById(id)); } общедоступный рецепт getRecipeById(длинный идентификатор) { return recipeRepository.findById(id) .orElseThrow(RecipeNotFoundException::new); } это все еще найти рецепт в БД
Итак, что вы сделали, так это то, что вы вызвали deleteRecipeById
API, затем вы вызвали getRecipes
API, и он все еще возвращает вам рецепт, который, по вашему мнению, должен был быть удален при вызове deleteRecipeById
?
также вы используете транзакцию?
вы убедились, что он был удален из БД?
нет, я не использую tansaction, он удален из базы данных, но полевой пользователь не знает об этом, и он сохранил рецепт в списке
где вы видите, что у пользователя все еще есть рецепт даже после его удаления?
/api/recipe/{id} по-прежнему возвращает рецепт с этим идентификатором
Можете показать код recipeService.getRecipeById
также, когда вы удаляете, вы на самом деле не выполняете полное удаление, вы просто отмечаете запись как удаленную, верно?
общедоступный рецепт getRecipeById (длинный идентификатор) { return recipeRepository.findById (id) .orElseThrow (RecipeNotFoundException:: new); }
я думаю, что я должен сделать жесткое удаление в БД
Хорошо, реальная проблема, учитывая информацию, которую вы разместили, заключается в том, что вы удаляете recipe
из user
, но не сохраняете user
после
Вы либо делаете:
1- Позвоните userRepository.save(currentUser)
, предварительно удалив recipe
у пользователя
ИЛИ лучше >
2- Аннотируйте deleteRecipeById
с @Transactional
, и это сделает работу
Если вам интересно, как № 2 будет выполнять эту работу, это потому, что когда вы загружаете объект из БД, говоря user
здесь, объект переходит в управляемое состояние, что означает, что если вы делаете какие-либо обновления для этого объекта, например recipes.remove(recipe);
тогда этот управляемый объект user
получает право на обновления, если вы находитесь в открытой транзакции и эта транзакция фиксируется [имеется в виду функция, аннотированная @Transactional
, подходит к концу], обновления этого управляемого объекта user
будут записаны в БД после фиксации транзакции, что приведет к обновить SQL-запрос, чтобы удалить этот receipe
у пользователя
* СОВЕТ, кстати, вы не можете использовать операцию записи в БД без области транзакции, тот факт, что вы удалили recipe
при вызове
recipeRepository.delete(currentRecipe);
это потому, что репозитории Spring по умолчанию аннотированы @Transactional
, и именно поэтому решение № 2 лучше, поскольку теперь вы будете использовать только одну транзакцию для обеих операций вместо решения № 1, которое выдает 2 транзакции
Что ты делаешь в
deleteFromUserList
?