简体   繁体   中英

JPA and Hibernate One To One Shared Primary Key Uni-directional Mapping in Spring Boot

I want to have one-to-one uni-directional mapping with 2 child entities using shared primary key. Below are model classes

public class Template implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "templatekey")
    Integer templateKey;

    @Column(name = "templateid", unique = true)
    String templateId;
    
    @OneToOne(cascade = CascadeType.ALL, optional = false)
    @PrimaryKeyJoinColumn(name = "templatekey", referencedColumnName = "templatekey")
    InstantOfferNoEsp instantOfferNoEsp;

    @OneToOne(cascade = CascadeType.ALL, optional = false)
    @PrimaryKeyJoinColumn(name = "templatekey", referencedColumnName = "templatekey")
    Mobile mobile;

     //constructor , setter and getters

}

Child 1 :

public class Mobile implements Serializable {
   
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "templatekey")
    Integer templateKey;
    
    String mobileNewUrl;


    //constructor , setter and getters

}

Child 2:

public class InstantOfferNoEsp {

    @Id
    @Column(name = "templatekey")
    Integer templateKey;

    String offerCodeType;

    String headerUrl;
 
    //constructor , setter and getters
}

I want templateKey as PK in all tables. and I am calling templateRepository.save(template); to save all entities at once but its not working and getting ids for this class must be manually assigned before calling save() error.

Any suggestions would be of great help. Thank you.

I was able to do what you want with bidirectional @OneToOne like below:

@Entity
public class Mobile {

    @Id
    Integer templateKey;
    
    @OneToOne
    @MapsId
    @JoinColumn(name = "templatekey")
    Template template;

    // ...
}

@Entity
public class InstantOfferNoEsp {

    @Id
    Integer templateKey;

    @OneToOne
    @MapsId
    @JoinColumn(name = "templatekey")
    Template template;
 
    // ...
}


@Entity
public class Template {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "templatekey")
    Integer templateKey;

    
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "template", optional = false)
    InstantOfferNoEsp instantOfferNoEsp;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "template", optional = false)
    Mobile mobile;

    // ...

    public void setMobile(Mobile mobile)
    {
        this.mobile = mobile;
        this.mobile.setTemplate(this);
    }

    public void setInstantOfferNoEsp(InstantOfferNoEsp instantOfferNoEsp)
    {
        this.instantOfferNoEsp = instantOfferNoEsp;
        this.instantOfferNoEsp.setTemplate(this);
    }
}

and an example of saving:

Mobile mobile = new Mobile();
mobile.setMobileNewUrl("MOB1");

InstantOfferNoEsp instant = new InstantOfferNoEsp();
instant.setOfferCodeType("INST_OFF1");
      
Template template = new Template();
template.setTemplateId("TMP1");
template.setInstantOffer(instant);
template.setMobile(mobile);
entityManager.persist(template);

PS The following mapping works too, but only if we set Template.templateKey manually.

@Entity
public class Template
{
   @Id
   // @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "templatekey")
   Integer templateKey;

   @OneToOne(cascade = CascadeType.ALL, optional = false)
   @JoinColumn(name = "templatekey", insertable = false, updatable = false)
   InstantOfferNoEsp instantOfferNoEsp;

   @OneToOne(cascade = CascadeType.ALL, optional = false)
   @JoinColumn(name = "templatekey", insertable = false, updatable = false)
   Mobile mobile;
 
   // ...
}

and an example of saving:

Mobile mobile = new Mobile();
mobile.setMobileNewUrl("MOB1");

InstantOfferNoEsp instant = new InstantOfferNoEsp();
instant.setOfferCodeType("INST_OFF1");
      
Template template = new Template();
template.setTemplateKey(20);
template.setTemplateId("TMP1");
template.setInstantOffer(instant);
template.setMobile(mobile);
entityManager.persist(template);

Also I would suggest your explicitly specify what generation strategy you want to use (do not use GenerationType.AUTO ) and use corresponding object wrapper classes instead of primitive types for @Id fields.

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