Spring Data JPA - Delete child entities instead of setting to null on update?
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
Admin
Updated on July 30, 2022Comments
-
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)