@PrimaryKeyJoinColumn 与双向 @OneToOne 关系 [英] @PrimaryKeyJoinColumn with Bidirectional @OneToOne relationship

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

问题描述

我有两个对象 Mat 和 MatImage,分别是父对象和子对象.MatImage 的主键是 Mat 的 id,它们通过一对一的关系连接.

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.

如果我正确理解双向关系,如果我执行 matImage.setMat(mat) 之类的操作,子对象就会知道父对象.我认为此时会填充主键,但事实并非如此.我知道这是因为 sql 在尝试插入带有 #0 作为 matId 的 MatImage 时抛出异常.

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.

另一个问题是关于 n+1 问题.我想延迟加载子对象,因为并非所有 mat 都有 matimage.我可以尝试将 @OneToOne 更改为 @ManyToOne 但不确定如何双向完成.任何帮助,将不胜感激.谢谢你.

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.

以下是实体:

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

}

现在我们的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);
    }

}

一些建议

JPA 规范没有包含一个标准化的方法处理共享主键生成问题

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

它解释了我为什么使用 org.apache.commons.lang.mutable.MutableInt 作为一种方式 MatMatImage 共享相同的内存中的对象(id).

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

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

Both will share the same generated id.

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

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.

问候,

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

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