简体   繁体   English

单向映射——父子实体的复合键

[英]Unidirectional mapping - composite keys of parent child entities

This is the code structure that I'm working on.这是我正在研究的代码结构。

@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;

I want to create one to many unidirectional mapping in which the parent's one part of primary key is being auto-generated and the other part is being sent in the Request Body during api call.我想创建一对多的单向映射,其中父键的一部分是自动生成的,另一部分是在 api 调用期间在请求正文中发送的。 Similarly, ca and cb will be sent in the Request Body during api call.同样,ca 和 cb 将在 api 调用期间在请求正文中发送。 I want to ensure that Pa also becomes part of composite primary key of the child.我想确保 Pa 也成为孩子复合主键的一部分。 the code below generates 2 tables parent_demo with (pa,pb) as primary key and child_demo with (pa,ca,cb) as primary key.下面的代码生成 2 个表 parent_demo 以 (pa,pb) 作为主键和 child_demo 以 (pa,ca,cb) 作为主键。 However, on doing the post api call, I get the violating not null constraint because pa from child_demo is null.但是,在执行 api 调用后,我得到了违反 not null 约束,因为来自 child_demo 的 pa 是 null。 I want to copy the value of pa (autogenerated ) in parent_demo to pa in child_demo.我想将 parent_demo 中的 pa(自动生成)的值复制到 child_demo 中的 pa。

Can someone help?有人可以帮忙吗?

There is an issue with your parent entity's primary key mapping, and there is no automated way to include a part of a parent's primary key in the primary key of a child entity.您的父实体的主键映射存在问题,并且没有自动方法将父主键的一部分包含在子实体的主键中。

Composite primary key mappings复合主键映射

Let's fix the primary key mapping of the parent entity first.我们先修复父实体的主键映射。 You can't use any mapping annotations on an IdClass .您不能在IdClass上使用任何映射注释。 You either need to change it to an @Embeddable and use it as an @EmbeddedId or move the mapping annotations to the entity class.您要么需要将其更改为@Embeddable并将其用作@EmbeddedId ,要么将映射注释移动到实体class。 I used the 2nd approach in the following mapping:我在以下映射中使用了第二种方法:

@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 
}

And you also should remove the @Id annotations from the ChildKey class.您还应该从ChildKey class 中删除@Id注释。

@Data
public class ChildKey implements Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private String ca; 
    
    private String cb;
    
    private String Pa;
}

Use parent primary key values使用父主键值

If the parent entity's entire primary key value becomes part of the child entity's primary key, you can use a @MapsId annotation on the association.如果父实体的整个主键值成为子实体主键的一部分,您可以在关联上使用@MapsId注释。 I explained that in great detail in this article .我在这篇文章中详细解释了这一点。

But that doesn't work if you only want to share one of the primary key attributes.但是,如果您只想共享一个主键属性,那将不起作用。 You then need to handle the primary key manually.然后您需要手动处理主键。 To persist a new parent with a new child entity, you first need to instantiate and persist the parent entity.要将新父实体与新子实体持久化,您首先需要实例化并持久化父实体。 That immediately sets the primary key value on that entity, and you can use it to instantiate and initialize your child entity.这会立即设置该实体的主键值,您可以使用它来实例化和初始化您的子实体。

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM