Java Spring数据JPA-删除子实体,而不是在更新时设置为null?
我有以下域模型Java Spring数据JPA-删除子实体,而不是在更新时设置为null?,java,mysql,spring,jpa,spring-data,Java,Mysql,Spring,Jpa,Spring Data,我有以下域模型 users ---- id (PK) name orders ------ id (PK) userid (PK) name Orders.userid引用用户中的id,并且是复合主键的一部分。(我需要主键中的userid,因为它是分区键,在MySQL中,没有分区键我们无法创建主键) 在使用JPA更新用户时,如果我尝试使用 User user = userRepository.getOne(id); user.getOrders().clear(); userReposito
users
----
id (PK)
name
orders
------
id (PK)
userid (PK)
name
Orders.userid引用用户中的id,并且是复合主键的一部分。(我需要主键中的userid,因为它是分区键,在MySQL中,没有分区键我们无法创建主键)
在使用JPA更新用户时,如果我尝试使用
User user = userRepository.getOne(id);
user.getOrders().clear();
userRepository.save(user);
JPA首先尝试将关联订单上的userid设置为null,然后删除该行。这会失败,因为userid不可为null,并且是主键的一部分。有没有办法告诉JPA,它只需要删除订单行,而不首先将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;
}
}
@实体
@表(name=“users”)
公共类用户实现可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“id”)
公共长id;
@列(name=“name”)
私有字符串名称;
@OneToMany(cascade=CascadeType.ALL,orphan=true)
@JoinColumn(name=“userid”,referencedColumnName=“id”,insertable=true,updateable=true)
@Fetch(FetchMode.JOIN)
私人定单;
}
@实体
@表(name=“orders”)
@IdClass(Order.OrderPk.class)
公共类顺序实现可序列化{
@身份证
@列(name=“id”)
私人长id;
@身份证
@列(name=“userid”)
私有长用户ID;
@列(name=“name”)
私有字符串名称;
公共静态类OrderPk实现可序列化{
私人长id;
私有长用户ID;
}
}
你能告诉我地图会有什么变化吗
更新:
也尝试了以下映射:
@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;
}
}
@实体
@表(name=“users”)
公共类用户实现可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“id”,nullable=false)
公共长id;
@列(name=“name”)
私有字符串名称;
@OneToMany(cascade=CascadeType.ALL,orphanRemoving=true,fetch=FetchType.EAGER,mappedBy=“orderPk.user”)
@Fetch(FetchMode.JOIN)
私人定单;
}
@实体
@表(name=“orders”)
公共类顺序实现可序列化{
@嵌入ID
私有OrderPk OrderPk;
@列(name=“name”)
私有字符串名称;
@可嵌入
公共静态类OrderPk实现可序列化{
@生成值
@列(name=“id”,insertable=false,updateable=false,nullable=false)
私人长id;
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“userid”,referencedColumnName=“id”,insertable=false,updateable=false,nullable=false)
私人用户;
}
}
在插入时,它抱怨说“为:类顺序生成的空id”
(也尝试过insertable=true和Updateable=true)这里的原因是关联是单向的,因此
用户
是拥有方(因为它是唯一的一方)
使关联双向,并使
成为关联所有者。这样,您将避免冗余更新(以及notnull
约束冲突)。以下实体映射适用于我。为了简洁起见,删除了所有的getter和setter
用户类
要删除的代码
生成的Sql
您可以使用标识符保留联接,并确保删除操作不会尝试使用集合上的可更新和可插入注释将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;
}
@实体
@表(name=“users”)
公共类用户实现可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“id”,nullable=false)
公共长id;
@列(name=“name”)
私有字符串名称;
@OneToMany(cascade=CascadeType.ALL,orphan=true,fetch=FetchType.EAGER)
@JoinColumn(name=“userId”,updateable=false,insertable=false)
私人定单;
}
@实体
@表(name=“orders”)
公共类顺序实现可序列化{
@身份证
@列(name=“id”)
私人长id;
@列(name=“userid”)
私有长用户ID;
@列(name=“name”)
私有字符串名称;
}
@JoinColumn(name=“userId”,updateable=false,insertable=false)
part意味着子表不会被更新,但可以被删除修复您的映射,其次,这确实是清除托管集合的糟糕方法。您不应允许从用户
对象外部修改集合。或者甚至可以从用户
中删除订单,只在订单上留下一个用户
字段,然后创建一个查询。@M.Deinum感谢您的回复,我已经用映射更新了问题。您能告诉我可以做哪些更改吗?本质上,我是在问如何处理具有非空外键的子实体。Inserts还将尝试首先使用空外键值进行insert,然后尝试将其更新为父键。在这种情况下,插入将失败,因为数据库不允许NULL。您真的需要订单上的组合PK吗?至少将其设置为updateable=false
和nullable=false
@M.Deinum,是的,我确实需要一个组合PK,因为partitionkey需要是PK的一部分。将其设置为Updateable=false和nullable=false似乎无法解决问题。只要我删除组合键关联,我假设当我们将关系设置为双向(因为joinkey将重复两次)时,情况就会很好。然而,这意味着我没有准确地映射到DB。问题是在实体中有一个复合键。我也用我尝试过的双向映射编辑了这个问题。它再次抱怨说不能按顺序设置空id。您确定这是用外键映射嵌入id的方法吗?
@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");
}
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=?
@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;
}