Hi i'm making application for recipe. One user could have many recipes and then he can delete his recipe. I store date in data base. User have a list of recipes in one of the field in db.I dont know what to do to delete a recipe on that list. I delete a recipe in db but is still on list in user field so we still can reach that recipe. I use JpaResporitory .There i give a part of my code. Could you help me please ?
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
there is how i save 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();
}
I tried googling that i read article about jpa but i still dont know what i have to do
Ok the real issue given info you posted, is that you remove recipe
from user
but you don't save user
after
You either do:
1- Call userRepository.save(currentUser)
, after removing recipe
from user
OR better >
2- Annotate deleteRecipeById
with @Transactional
and it will do the job
If you wonder how no.2 will do the job, it is because when you load entity from DB talking user
here, the entity becomes in a Managed state meaning that if you do any updates to that entity like recipes.remove(recipe);
then this managed entity user
becomes eligible for updates, if you are in an opened transaction and that transaction gets committed [meaning function annotated with @Transactional
comes to end] that managed entity user
updates will be written to DB since transaction is committed, which will issue update SQL query to remove that receipe
from user
*TIP, BTW, you can not use write operation against DB without a transaction scope, the fact you deleted recipe
when you called
recipeRepository.delete(currentRecipe);
it is because Spring Repositories are annotated with @Transactional
by default and that is why solution no 2 is better since now you would use only one transaction for both operations instead of the solution no 1 that would issue 2 transactions