Spring Data JPA - Delete child entities instead of setting to null on update?

10,320

You can keep the join using the identifier, and ensure the delete doesn't attempt to write null to the collection FK using the updatable and insertable annotations on the collection.

@Entity
@Table(name = "users")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id", nullable = false)
    public Long id;

    @Column(name="name")
    private String name;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch =     FetchType.EAGER)
    @JoinColumn(name = "userId", updatable = false, insertable = false)
    private Set<Order> orders;
}

@Entity
@Table(name = "orders")
public class Order implements Serializable {

    @Id
    @Column(name="id")
    private Long id;

    @Column(name="userid")
    private Long userId;

    @Column(name="name")
    private String name;
}

The

@JoinColumn(name = "userId", updatable = false, insertable = false)

part means the child table won't be updated, but can be deleted

Share:
10,320
Admin
Author by

Admin

Updated on July 30, 2022

Comments

  • Admin
    Admin almost 2 years

    I have the following domain model

    users
    ----
    id (PK)
    name
    
    orders
    ------
    id (PK)
    userid (PK)
    name
    

    Orders.userid references id in User and is part of the composite primary key. (I need userid in the primary key since it is a partition key and in MySQL we cannot create the primary key without the partition key)

    On using JPA to update User, if I try to clear the associated orders collection using

    User user = userRepository.getOne(id);
    user.getOrders().clear();
    userRepository.save(user);
    

    JPA first tries to set userid to null on the associated Orders and then delete the row. This fails since userid is non-nullable and part of the primary key. Is there a way to tell JPA that it simply needs to go an delete the Order rows without setting the userid column to null first?

    UPDATE

    Mapping: The mapping I have is something like this:

    @Entity
    @Table(name = "users")
    public class User implements Serializable {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name="id")
        public Long id;
    
        @Column(name="name")
        private String name;
    
        @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
        @JoinColumn(name="userid", referencedColumnName = "id", insertable = true, updatable = true)
        @Fetch(FetchMode.JOIN)
        private Set<Order> orders;
    
    }
    
    @Entity
    @Table(name = "orders")
    @IdClass(Order.OrderPk.class)
    public class Order implements Serializable {
    
        @Id
        @Column(name="id")
        private Long id;
    
        @Id
        @Column(name="userid")
        private Long userId;
    
        @Column(name="name")
        private String name;
    
        public static class OrderPk implements Serializable  {
    
            private Long id;
    
            private Long userId;
        }
    }
    

    Can you tell me what would be the change to the mapping?

    UPDATE:

    Tried the following mapping too:

    @Entity
    @Table(name = "users")
    public class User implements Serializable {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name="id", nullable = false)
        public Long id;
    
        @Column(name="name")
        private String name;
    
        @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "orderPk.user")
        @Fetch(FetchMode.JOIN)
        private Set<Order> orders;
    }
    
    @Entity
    @Table(name = "orders")
    public class Order implements Serializable {
    
        @EmbeddedId
        private OrderPk orderPk;
    
        @Column(name="name")
        private String name;
    
        @Embeddable
        public static class OrderPk implements Serializable {
    
            @GeneratedValue
            @Column(name="id", insertable = false, updatable = false, nullable = false)
            private Long id;
    
            @ManyToOne(fetch = FetchType.LAZY)
            @JoinColumn(name="userid", referencedColumnName = "id", insertable = false, updatable = false, nullable = false)
            private User user;
        }
    }
    

    On insert, it complains saying "null id generated for:class Order" (Have also tried with insertable=true and updatable=true)