I'm working on e-commerce APIs, I have this service that is responsible for the cart operation:
@Service
@AllArgsConstructor
public class CartService implements ICartService {
private final CartRepository cartRepository;
private final CartItemRepository cartItemRepository;
private final CartMapper cartMapper;
...
@Transactional
@Override
public void clearCart(Long id) {
// Delete all cart items first
cartItemRepository.deleteByCartId(id);
Optional<Cart> cart = cartRepository.findById(id);
if (cart.isPresent()) {
cartRepository.deleteById(id);
} else {
throw new ResourceNotFoundException("Cart not found for ID: " + id);
}
}
...
}
the cartItemRepository.deleteByCartId(id);
works just fine, it deletes all the cart items from the database, but the part responsible for the deletion of the cart itself doesn't work, the cart data still in the database, but when I add a new item to the cart after deletion, the previous data get deleted and the new data replace the old one!
Here is how my cart entity looks:
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Cart {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
private Long id;
private BigDecimal totalAmount = BigDecimal.ZERO;
@OneToMany(
mappedBy = "cart",
cascade = CascadeType.ALL,
orphanRemoval = true
)
@JsonManagedReference
private Set<CartItem> items = new HashSet<>();
@OneToOne
@JoinColumn(name = "user_id")
private User user;
public void addItem(CartItem item) {
this.items.add(item);
item.setCart(this);
updateTotalAmount();
}
public void removeItem(CartItem item) {
this.items.remove(item);
item.setCart(null);
updateTotalAmount();
}
private void updateTotalAmount() {
this.totalAmount = items.stream().map(item -> {
BigDecimal unitPrice = item.getUnitPrice();
if (unitPrice == null) {
return BigDecimal.ZERO;
}
return unitPrice.multiply(BigDecimal.valueOf(item.getQuantity()));
}).reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
I thought the problem with the relationship with the user entity, here is the user entity:
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class User {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
private Long id;
private String firstName;
private String lastName;
private String email;
private String password;
@OneToOne(mappedBy = "user",
cascade = CascadeType.ALL,
orphanRemoval = true)
private Cart cart;
@OneToMany(
mappedBy = "user",
cascade = CascadeType.ALL,
orphanRemoval = true
)
@JsonManagedReference
private List<Order> orders;
}
I added cascade detach to the user property in the cart entity:
@OneToOne(
cascade = CascadeType.DETACH
)
@JoinColumn(name = "user_id")
private User user;
and also didn't work, I also tried to enforce deletion from the db, but also didn't work:
cartItemRepository.deleteByCartId(id);
entityManager.remove(cart.get()); // Forces deletion from DB