Home > OS >  Can't remove element from collection in OneToMany side
Can't remove element from collection in OneToMany side

Time:10-04

I am developing online store app and I'm struggling with purchase system. Generally I need to write service which works with steps:

  • Check whether customer has sufficient funds for payment
  • If he does - subtract amount of product's cost from Customer's balance
  • Delete Product from Customer collection (this doesn't work!)
  • Save Customer with updated collection to database
  • Delete Product from database

However, no matter how I try to do this, Product is not deleted from Customer collection. remove() method, clear() method, etc., nothing works. Every time I log Customer collection to console after purchase, purchased Product still belongs to Customer who posted Product. This major problem causes many bugs which - for example - regard saving Customer with non-existing Product (since in next purchase, saving Customer includes non-deleted previous Product in Customer collection).

Snippets of code:

Piece of Service:

public boolean processPayment(Customer customerToEdit, Product productToOperate) {
        if (customerToEdit.getBalance() >= productToOperate.getProductCost())
        {
            Customer retrievedProductOwner = productToOperate.getProductOwner();
            customerToEdit.setBalance(customerToEdit.getBalance()-productToOperate.getProductCost());
/* This doesn't execute! */
            retrievedProductOwner.getOwnedProducts().remove(productToOperate);
            customerDAO.save(retrievedProductOwner);
        }
        else {
            System.out.println("Insufficient funds!");
            return false;
        }
        return true;
    }

Piece of Controller:

@GetMapping("/showOffer")
    public String getOffer(@RequestParam("offerId") int offerId, Model theModel, @AuthenticationPrincipal MyUserDetails user) {
        Product retrievedProduct = productService.findById(offerId);
        if (customerService.processPayment(user.getCustomer(), retrievedProduct)) {
            productService.delete(retrievedProduct.getId());
        }
        return "redirect:/home";
    }

Product.java:

@Entity
@Table(name="product")
public class Product {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private int id;
    
    @Column(name="name")
    private String productName;
    
    @Column(name="description")
    private String productDescription;
    
    @Column(name="category")
    private String productCategory;
    
    @Column(name="cost")
    private int productCost;
    
    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="owner_id")
    private Customer productOwner;
/* (...) */

Customer.java:

@Entity
@Table(name="customer")
public class Customer {

    //Class fields
    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private int id;
    
    @Column(name="balance")
    private int balance;
    
    @Column(name="first_name")
    private String firstName;
    
    @Column(name="last_name")
    private String lastName;


    @Column(name="email")
    private String email;
    
    @OneToMany(mappedBy="productOwner", fetch=FetchType.EAGER)
    private List<Product> ownedProducts;
/* (...) */

CodePudding user response:

You need to enable orphan removal of products by adding CascadeType.PERSIST and orphan removal true

@OneToMany(mappedBy = "productOwner", fetch = FetchType.EAGER, cascade = CascadeType.PERSIST, orphanRemoval = true)
private List<Product> ownedProducts = new ArrayList<>();

When you save the customer this should trigger delete of the removed Product

  • Related