这是我正在研究的代码结构。
@Data
public class ParentKey implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(generator= "uuid")
@GenericGenerator(name="uuid", strategy="uuid2")
private String Pa;
@Id
private String Pb;
// ignoring getters and setters and hashcode and equals()
}
@Entity
@IdClass(ParentKey.class)
@Table(name="parent_demo")
public class Parent_Demo {
@Id
private String Pa;
@Id
// @Column(name="p_b")
private String Pb;
@OneToMany(cascade=CascadeType.ALL,orphanRemoval=true )
@JoinColumn(name="p_a_fk", referencedColumnName="Pa")
@JoinColumn(name="p_b_fk", referencedColumnName="Pb")
private List<Child_Demo> childs = new ArrayList<>();
private String pc;
// ignoring getter and setters
}
@Data
public class ChildKey implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
private String ca;
@Id
private String cb;
@Id
private String Pa;
}
@Entity
@IdClass(ChildKey.class)
@Table(name="child_demo")
public class Child_Demo {
@Id
private String Pa; // can i link this value to the value of Pa in ParentKey which is being autogenerated
@Id
private String ca;
@Id
private String cb;
private String cc;
private String cd;
我想创建一对多单向映射,其中父键的一部分是自动生成的,另一部分是在 api 调用期间在请求正文中发送。类似地,在api调用期间,将在请求正文中发送ca和cb。我想确保 Pa 也成为孩子复合主键的一部分。 下面的代码生成 2 个表 parent_demo 以 (pa,pb) 作为主键和 child_demo 以 (pa,ca,cb) 作为主键。但是,在执行 post api 调用时,我得到了违反 not null 约束,因为 child_demo 中的 pa 为空。我想将 parent_demo 中的 pa(自动生成)的值复制到 child_demo 中的 pa。
有人可以帮忙吗?
答案 0 :(得分:0)
您的父实体的主键映射存在问题,并且没有自动方法将父实体的主键的一部分包含在子实体的主键中。
复合主键映射
我们先修复父实体的主键映射。您不能在 IdClass
上使用任何映射注释。您需要将其更改为 @Embeddable
和 use it as an @EmbeddedId
,或者将映射注释移至实体类。我在以下映射中使用了第二种方法:
@Data
public class ParentKey implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String Pa;
private String Pb;
// ignoring getters and setters and hashcode and equals()
}
@Entity
@IdClass(ParentKey.class)
@Table(name="parent_demo")
public class Parent_Demo {
@Id
@GeneratedValue(generator= "uuid")
@GenericGenerator(name="uuid", strategy="uuid2")
private String Pa;
@Id
private String Pb;
@OneToMany(cascade=CascadeType.ALL,orphanRemoval=true )
@JoinColumn(name="p_a_fk", referencedColumnName="Pa")
@JoinColumn(name="p_b_fk", referencedColumnName="Pb")
private List<Child_Demo> childs = new ArrayList<>();
private String pc;
// ignoring getter and setters
}
您还应该从 @Id
类中删除 ChildKey
注释。
@Data
public class ChildKey implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String ca;
private String cb;
private String Pa;
}
使用父主键值
如果父实体的整个主键值成为子实体主键的一部分,您可以在关联上使用 @MapsId
注释。我在 this article 中详细解释了这一点。
但是如果您只想共享主键属性之一,那将不起作用。然后您需要手动处理主键。要使用新的子实体持久化新的父实体,您首先需要实例化并持久化父实体。这会立即在该实体上设置主键值,您可以使用它来实例化和初始化您的子实体。
Parent_Demo p = new Parent_Demo();
p.setPb("something");
// initialize more attributes ...
em.persist(p); // or parentRepo.save(p);
Child_Demo c = new Child_Demo();
c.setPa(p.getPa());
// initialize more attributes ...
em.persist(c);