我有两个对象Mat和MatImage,父母和孩子分别。 MatImage的主键是Mat的ID,它们之间是一对一的关系。
如果我正确理解了双向关系,那么如果我执行matImage.setMat(mat)之类的操作,子对象将了解父对象。我认为主键将在此时填充,但事实并非如此。我知道这是因为sql在尝试将#0作为matId插入MatImage时引发异常。
另一个问题是n + 1问题。我想延迟加载子对象,因为并非所有垫子都具有matimage。我可以尝试将@OneToOne更改为@ManyToOne,但不确定如何双向进行。任何帮助,将不胜感激。谢谢。
以下是实体:
// 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
...
}
最佳答案
我不确定你是否真的想要。但是,您可以使用以下类似方法来建立双向关系。
@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规范不包含处理共享主键生成问题的标准化方法
它解释了为什么我使用
org.apache.commons.lang.mutable.MutableInt
作为Mat
和MatImage
在内存中共享相同对象(id)的方式。现在,您可以使用类似以下的内容:
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。
建议:将注释配置放在getter方法中,而不是在成员字段中。 Hibernate使用代理对象。但是代理在getter方法中使用批注时效果很好,而不是在成员字段中使用时效果很好。
问候,