具有双向@OneToOne关系的@PrimaryKeyJoinColumn [英] @PrimaryKeyJoinColumn with Bidirectional @OneToOne relationship

查看:139
本文介绍了具有双向@OneToOne关系的@PrimaryKeyJoinColumn的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个对象Mat和MatImage,父母和孩子resp。 MatImage的主键是Mat的id,它们通过一对一的关系进行连接。

如果我正确理解双向关系,那么如果我执行像matImage.setMat(mat)这样的操作,子对象将知道父对象。我认为在这一点上主要关键将被填补,但事实并非如此。我知道这是因为sql在尝试以#0作为matId插入MatImage时抛出异常。



另一个问题是n + 1问题。我想懒惰地加载子对象,因为不是所有的垫都有matimage。我可以尝试将@OneToOne更改为@ManyToOne,但不知道如何双向完成。任何帮助,将不胜感激。谢谢。



以下是实体:

  // Mat 

@Entity
@Table(name =mat)
public class Mat实现Serializable {
@Id
@GeneratedValue(generator =SeqMat)
@SequenceGenerator(name =SeqMat,sequenceName =seq_mat_id)
int id

@OneToOne(mappedBy =mat,optional = true,fetch = FetchType.LAZY )
@PrimaryKeyJoinColumn(name =id,referencedColumnName =matId)
@Cascade([ALL,DELETE_ORPHAN])
MatImage matImage

int matTemplateId
int number
...
}


// MatImage
@Entity
@Table(name =matimage )
public class MatImage implements Serializable {
@Id
int matId

@OneToOne(optional = true,fetch = FetchType.LAZY)
@JoinColumn (name =matId,referencedColumnName =id)
Mat mat

@Column(name =img_eventid)
int eventId

...
}


解决方案

我是不确定你真的想要。但是您可以使用类似于以下内容的设置来建立双向关系。

  @Entity 
public class Mat实现Serializable {

private MutableInt id = new Mutable (-1);

私人MatImage matImage;

@Id
@GeneratedValue(strategy = GenerationType.AUTO,generator =SeqMat)
@SequenceGenerator(name =SeqMat,sequenceName =seq_mat_id)
public Integer getId(){
return this.id.intValue;

$ b $ 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);
}

}

现在我们的 MatImage

  @Entity 
公共类MatImage实现Serializable {

private MutableInt id = new MutableInt(-1);

私人餐垫;

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

$ b $ @ @OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
public Mat getMat(){
return mat;
}

public void setMat(Mat mat){
this.mat = mat;

this.mat.setIdAsMutableInt(this.id);
}

}

一些建议


JPA规范不包含标准化方法来处理共享主键生成问题


它解释了为什么我使用 org.apache.commons.lang.mutable.MutableInt Mat MatImage 在内存中共享同一个对象(id)



现在你可以使用类似于:

  Mat mat = new Mat(); 
MatImage matImage = new MatImage();

/ **
*设置双方
*
*或者使用某种添加便利方法把它的车
* /
mat.setImage(matImage);
matImage.setMat(mat);

session.saveOrUpdate(mat);

两者将共享相同的生成ID。



建议:将注释配置放在getter方法而不是成员字段中。 Hibernate使用代理对象。但是,在getter方法中使用注释时,代理工作正常,而不是在成员字段中使用时。



问候,


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 understand bidirectional relation correctly, the child object would know about the parent if I do something like matImage.setMat(mat). I would think the primary key would be filled at this point, but it doesn't. I know this because sql throws an exception when it try to insert MatImage with #0 as matId.

Another question is with the n+1 problem. I would like to lazily load child object because not all mat has matimage. I can try changing @OneToOne to @ManyToOne but not sure how that can be done bidirectionally. Any help would be appreciated. Thank you.

Here are the entities:

// Mat

@Entity
@Table(name="mat")
public class Mat implements Serializable {
 @Id
 @GeneratedValue(generator="SeqMat")
 @SequenceGenerator(name="SeqMat", sequenceName="seq_mat_id")
    int id

    @OneToOne(mappedBy="mat", optional=true, fetch=FetchType.LAZY)
 @PrimaryKeyJoinColumn(name="id", referencedColumnName="matId")
 @Cascade([ALL, DELETE_ORPHAN])
 MatImage matImage

    int matTemplateId
    int number
    ... 
}


     // MatImage
    @Entity
    @Table(name="matimage")
    public class MatImage implements Serializable {
        @Id
        int matId

        @OneToOne(optional=true, fetch=FetchType.LAZY)
        @JoinColumn(name="matId", referencedColumnName="id")
        Mat mat

        @Column(name="img_eventid")
        int eventId

        ...
}

解决方案

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,

这篇关于具有双向@OneToOne关系的@PrimaryKeyJoinColumn的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆