title: JPA 1:N relationship removing child does not remove it from parent
body: <p>I have the following objects:</p>
  <pre><code>@NoArgsConstructor
  @AllArgsConstructor
  @Getter
  @Entity(name=&quot;Group&quot;)
  public class Group {
      @Id
      @GeneratedValue
      @NotNull
      @Column(name = &quot;GROUP_ID&quot;)
      private Long id;
  
      @Column(name=&quot;NAME&quot;)
      private String name;
  
      @OneToMany(
              targetEntity = Product.class,
              mappedBy = &quot;groupId&quot;,
              cascade = CascadeType.ALL,
              fetch = FetchType.EAGER,
              orphanRemoval = true
      )
      private List&lt;Product&gt; products = new ArrayList&lt;&gt;();
  
      public Group(String name) {
          this.name = name;
      }
  </code></pre>
  <pre><code>@Getter
  @Setter
  @AllArgsConstructor
  @NoArgsConstructor
  @Entity(name=&quot;Product&quot;)
  public class Product {
      @Id
      @GeneratedValue
      @NotNull
      @Column(name=&quot;PRODUCT_ID&quot;)
      private Long id;
  
      @Column(name=&quot;NAME&quot;)
      private String name;
  
      @Column(name=&quot;DESCRIPTION&quot;)
      private String description;
  
      @Column(name=&quot;PRICE&quot;)
      private double price;
  
      @ManyToMany
      @JoinTable(
              name = &quot;JOIN_PRODUCT_CART&quot;,
              joinColumns = {@JoinColumn(name = &quot;PRODUCT_ID&quot;, referencedColumnName = &quot;PRODUCT_ID&quot;)},
              inverseJoinColumns = {@JoinColumn(name = &quot;CART_ID&quot;, referencedColumnName = &quot;CART_ID&quot;)}
      )
      private List&lt;CartEntity&gt; carts = new ArrayList&lt;&gt;();
  
      @ManyToOne
      @JoinColumn(name = &quot;GROUP_ID&quot;)
      private Group groupId;
  
      public Product(String name, String description, double price) {
          this.name = name;
          this.description = description;
          this.price = price;
      }
  
      public Product(String name, String description, double price, Group groupId) {
          this(name, description, price);
          this.groupId = groupId;
      }
  
      public void addToCart(CartEntity cart) {
          this.carts.add(cart);
          cart.getProductsList().add(this);
      }
  
      public void addGroup(Group group) {
          group.getProducts().add(this);
          this.groupId = group;
      }
  </code></pre>
  <pre><code>@Getter
  @NoArgsConstructor
  @AllArgsConstructor
  @Entity(name = &quot;cart&quot;)
  public class CartEntity {
  
      @Id
      @NotNull
      @GeneratedValue
      @Column(name = &quot;CART_ID&quot;)
      private Long id;
  
      @ManyToMany(cascade = CascadeType.ALL, mappedBy = &quot;carts&quot;)
      private List&lt;Product&gt; productsList = new ArrayList&lt;&gt;();
  
      public void addProduct(Product product) {
          productsList.add(product);
          product.getCarts().add(this);
      }
  
      @Override
      public boolean equals(Object o) {
          if (this == o) return true;
          if (o == null || getClass() != o.getClass()) return false;
          CartEntity that = (CartEntity) o;
          return id.equals(that.id);
      }
  
      @Override
      public int hashCode() {
          return Objects.hash(id);
      }
  }
  </code></pre>
  <p>Now, when I have the following test:</p>
  <pre><code>public class ProductDaoTestSuite {
      @Autowired
      private ProductDao productDao;
      @Autowired
      private CartDaoStub cartDaoStub;
      @Autowired
      private GroupDao groupDao;
  
      @Test
      public void testDeleteProduct() {
          // Given
          Product product = new Product(&quot;test&quot;, &quot;testProduct&quot;, 100.0);
          Group group = new Group(&quot;group1&quot;);
          CartEntity cart = new CartEntity();
  
          product.addGroup(group);
          cart.addProduct(product);
  
          // When
          groupDao.save(group);
          productDao.save(product);
          cartDaoStub.save(cart);
  
          Long groupId = group.getId();
          Long productId = product.getId();
          Long cartId = cart.getId();
  
          productDao.deleteById(productId);
  
          // Then
          Assert.assertTrue(cartDaoStub.findById(cartId).isPresent());
          Assert.assertEquals(0, cartDaoStub.findById(cartId).get().getProductsList().size());
  
          Assert.assertTrue(groupDao.findById(groupId).isPresent());
          Assert.assertEquals(0, groupDao.findById(groupId).get().getProducts().size());
  </code></pre>
  <p>Following product deletion, I would expect association with it in group and cart to disappear (product to disappear from their List relationship fields). However, that is not happening at the moment. When I use Group/Cart Dao to pull group &amp; cart from the DB after product deletion, they still have product in their Lists, while product when pulled from the DB is returned as null.
  I have tried to add &quot;orphanRemoval = true&quot; value for @OneToMany adnotation, but it did not seem to work for Group entity.</p>
  <p>What am I doing wrong?</p>
  <p>I have started experimenting with adding all types of cascade (except for REMOVE) to @ManyToOne on Product class, but so far no luck.</p>