我有以下域名模型
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;
}
}
在插入时,它抱怨说“为类命令生成了null id” (还尝试过insertable = true和updatable = true)
答案 0 :(得分:0)
这里的原因是关联是单向的,所以User
是拥有方(因为它是唯一的一方)。
使关联成为双向关联,并使Order
成为关联所有者。这样您就可以避免冗余更新(以及not null
约束违规)。
答案 1 :(得分:0)
以下实体映射适用于我。为简洁起见,删除了所有的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=?
答案 2 :(得分:0)
您可以使用标识符保留连接,并确保删除操作不会尝试使用集合上的可更新和可插入注释将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”,可更新=假,可插入=假)
part表示子表不会被更新,但是可以被删除