@PrimaryKeyJoinColumn with Bidirectional @OneToOne relationship

后端 未结 2 1396
太阳男子
太阳男子 2020-12-10 08:28

I have two objects Mat and MatImage, parent and child resp. The primary key of MatImage is the id of Mat and they are join by one to one relationship.

If I understa

2条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-10 09:22

    I am not sure about you really want. But you can use something like the following one to set up your bidirectional relationship.

    @Entity
    public class Mat implements Serializable {
    
        private MutableInt id = new Mutable(-1);
    
        private MatImage matImage;
    
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO, generator="SeqMat")
        @SequenceGenerator(name="SeqMat", sequenceName="seq_mat_id")
        public Integer getId() {
            return this.id.intValue;
        }
    
        public void setId(Integer id) {
            this.id.setValue(id)
        }
    
        public void setIdAsMutableInt(MutableInt id) {
            this.id = id;
        }
    
        @OneToOne(fetch=FetchType.LAZY)
        @PrimaryKeyJoinColumn
        @Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})
        public MatImage getMatImage() {
            return this.matImage;
        }
    
        public void setMatImage(MatImage matImage) {
            this.matImage = matImage;
    
            this.matImage.setIdAsMutableInt(this.id);
        }
    
    }
    

    Now our MatImage

    @Entity
    public class MatImage implements Serializable {
    
        private MutableInt id = new MutableInt(-1);
    
        private Mat mat;
    
        @Id
        public Integer getId() {
            return this.id.intValue();
        }
    
        public void setId(Integer id) {
            this.id.setValue(id);
        }
    
        public void setIdAsMutableInt(MutableInt id) {
            this.id = id;
        }
    
        @OneToOne(fetch=FetchType.LAZY)
        @PrimaryKeyJoinColumn
        public Mat getMat() {
            return mat;
        }
    
        public void setMat(Mat mat) {
            this.mat = mat;
    
            this.mat.setIdAsMutableInt(this.id);
        }
    
    }
    

    A couple of advice

    JPA specification does not include a standardized method to deal with the problem of shared primary key generation

    It explains why I use a org.apache.commons.lang.mutable.MutableInt as a way both Mat and MatImage share the same object (id) in memory.

    Now you can use something like:

    Mat mat = new Mat();
    MatImage matImage = new MatImage();
    
    /**
      * Set up both sides
      * 
      * Or use some kind of add convenience method To take car of it
      */
    mat.setImage(matImage);
    matImage.setMat(mat);
    
    session.saveOrUpdate(mat);
    

    Both will share the same generated id.

    Advice: put annotation configuration in getter method instead of member field. Hibernate makes use of proxy objects. But proxy works fine when using annotation in getter method, not when using in member field.

    regards,

提交回复
热议问题