简体   繁体   中英

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. Similarly, ca and cb will be sent in the Request Body during api call. I want to ensure that Pa also becomes part of composite primary key of the child. the code below generates 2 tables parent_demo with (pa,pb) as primary key and child_demo with (pa,ca,cb) as primary key. However, on doing the post api call, I get the violating not null constraint because pa from child_demo is null. I want to copy the value of pa (autogenerated ) in parent_demo to pa in child_demo.

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 . You either need to change it to an @Embeddable and use it as an @EmbeddedId or move the mapping annotations to the entity 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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