![](/img/trans.png)
[英]Setting NULL value in UPDATE query of Native JPA in Spring data
[英]Spring Data JPA - Delete child entities instead of setting to null on update?
我有以下域模型
users
----
id (PK)
name
orders
------
id (PK)
userid (PK)
name
Orders.userid 引用 User 中的 id 並且是復合主鍵的一部分。 (我需要在主鍵中使用 userid,因為它是一個分區鍵,而在 MySQL 中我們不能在沒有分區鍵的情況下創建主鍵)
在使用 JPA 更新用戶時,如果我嘗試使用清除關聯的訂單集合
User user = userRepository.getOne(id);
user.getOrders().clear();
userRepository.save(user);
JPA 首先嘗試將關聯訂單上的 userid 設置為 null,然后刪除該行。 這將失敗,因為 userid 不可為空並且是主鍵的一部分。 有沒有辦法告訴 JPA 它只需要刪除 Order 行而不先將 userid 列設置為 null?
映射:我擁有的映射是這樣的:
@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;
}
}
你能告訴我映射會有什么變化嗎?
也嘗試了以下映射:
@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;
}
}
在插入時,它抱怨說“為:class Order 生成了 null id”(也嘗試過使用 insertable=true 和 updatable=true)
您可以使用標識符保持連接,並確保刪除不會嘗試使用集合上的可更新和可插入注釋將 null 寫入集合 FK。
@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;
}
這
@JoinColumn(name = "userId", updatable = false, insertable = false)
part 表示子表不會更新,但可以刪除
這里的原因是關聯是單向的,所以User
是擁有方(因為它是唯一的一方)。
使關聯雙向並使Order
成為關聯所有者。 這樣您就可以避免冗余更新(而not null
違反not null
約束)。
以下實體映射對我有用。 為簡潔起見,刪除了所有 getter 和 setter。
用戶類
@Entity
public class User {
@Id
@GeneratedValue
private Integer id;
private String name;
@OneToMany(mappedBy = "userId", cascade = { CascadeType.ALL }, orphanRemoval = true)
private List<Orders> orders;
public void removeOrder(Orders orders) {
orders.setUserId(null);
this.orders.remove(orders);
}
public void removeAllOrders() {
orders.forEach(order -> order.setUserId(null));
this.orders.clear();
}
}
訂單類
@Entity
@IdClass(Orders.OrderPk.class)
public class Orders {
@Id
private Integer id;
@Id
@ManyToOne
@JoinColumn(name = "userid")
private User userId;
private String name;
public static class OrderPk implements Serializable {
private Integer id;
private Integer userId;
}
}
要刪除的代碼
@Override
@Transactional
public void run(String... args) throws Exception {
User user = userRepository.findOne(1);
user.removeAllOrders();
userRepository.save(user);
System.out.println("Done");
}
生成的sql
Hibernate: select user0_.id as id1_1_0_, user0_.name as name2_1_0_ from user user0_ where user0_.id=?
Hibernate: select orders0_.userid as userid2_1_0_, orders0_.id as id1_0_0_, orders0_.userid as userid2_0_0_, orders0_.id as id1_0_1_, orders0_.userid as userid2_0_1_, orders0_.name as name3_0_1_ from orders orders0_ where orders0_.userid=?
Done
Hibernate: delete from orders where id=? and userid=?
Hibernate: delete from orders where id=? and userid=?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.