Java Hibernate-使用生成的复合键插入临时子实体
我在使用Hibernate插入一组临时子实体时遇到了问题,通过保存分离的父实体,这些子实体可能具有由其他临时子实体组成的复合键。我非常确定我已经正确设置了复合键类,但是每次我尝试保存具有临时实体(尚未生成ID)的父实体时,我都会遇到以下错误:Java Hibernate-使用生成的复合键插入临时子实体,java,hibernate,jpa,Java,Hibernate,Jpa,我在使用Hibernate插入一组临时子实体时遇到了问题,通过保存分离的父实体,这些子实体可能具有由其他临时子实体组成的复合键。我非常确定我已经正确设置了复合键类,但是每次我尝试保存具有临时实体(尚未生成ID)的父实体时,我都会遇到以下错误: org.hibernate.id.IdentifierGenerationException: null id generated for:class org._.website.data.entity.Mean 所以Hibernate从不生成复合键,我
org.hibernate.id.IdentifierGenerationException: null id generated for:class org._.website.data.entity.Mean
所以Hibernate从不生成复合键,我认为在给定所引用的属性的情况下,它应该能够生成复合键。但是,由于复合键引用的属性也是瞬态的,因此没有可用于手动设置复合键的ID。所以我希望Hibernate足够聪明,可以自己完成这一代
有没有办法让Hibernate使用引用其他瞬态子实体的复合键来处理瞬态子实体的保存/插入
这是我正在使用的代码。如果projectDao.save(项目)失败
如果有帮助,下面是可嵌入的MeanPK类
@Embeddable
public static class MeanPK implements Serializable {
private static final long serialVersionUID = 341373316515655834L;
@GeneratedValue
@Column(name = "belief_id", nullable = false, updatable = false)
protected Integer beliefId;
@GeneratedValue
@Column(name = "variable_id", nullable = false, updatable = false)
protected Integer variableId;
// getters/setters excluded for brevity
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof MeanPK)) {
return false;
}
MeanPK other = (MeanPK) obj;
return beliefId.equals(other.beliefId) && variableId.equals(other.variableId);
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(beliefId).append(variableId).toHashCode();
}
}
如果必须的话,我可以先保存复合键引用的临时实体,以获取ID并手动构造MeanPK复合键,但我希望Hibernate能够通过调用projectDao.save(…)单独处理这个问题
谢谢你的帮助 研究在实体类上使用级联注释。。。保存操作将尝试在Mean具有ID之前保存项目。尝试执行projectDao.save(Mean);首先,或者对项目类上的平均集合使用级联注释 就像这样
Mean mean = new Mean();
mean.setVariable(variable);
mean.setBelief(belief);
**projectDao.save(mean);** //first option
// I can't do this because variable and belief are transient and have no ID yet
//MeanPK meanPk = new MeanPK(variableId, beliefId);
//mean.setPk(meanPk);
belief.getMeans().add(mean);
project.getVariables().add(variable);
project.getBeliefs().add(belief);
projectDao.save(project);
//second option
//or in your method declaration section in your Project class remove
getVariables().add(variable) &
getBeliefs().add(belief)
//as well as their associated variable declarations and add
// mappedBy foreign key constraint meanId
@OneToMany(cascade = CascadeType.ALL, mappedBy = "meanId")
//add to variable declarations section
private Collection<Means> meansCollection;
//and add the following method under getter/setter section
@XmlTransient
public Collection<Mean> getMeansCollection() {
return meansCollection;
}
//In the Project class constructor do the following initialization of the MeanCollection
meansCollection = new ArrayList();
//now your call simply becomes
Mean mean = new Mean();
mean.setVariable(variable);
mean.setBelief(belief);
Project project = new Project();
project.getMeansCollection().add(means);
projectDao.save(project);
// Also it looks like you should be using @JoinColumns for the variable_id &
// belief_id fields where each variable is actually a class variable
// representation and not an Integer. In this case you will have mean_id as
// the single primary key and class Variable & Belief each as a @JoinColumn
// foreign key constraint
//4 spaces
平均值=新平均值();
平均值。设置变量(变量);
挫折信念(信念);
**projectDao.save(平均值);**//第一购股权
//我不能这样做,因为变量和信念是暂时的,还没有ID
//MeanPK MeanPK=新的MeanPK(variableId,beliefId);
//平均setPk(平均PK);
belience.getMeans().add(mean);
project.getVariables().add(变量);
project.getbelies().add(信念);
projectDao.save(project);
//第二种选择
//或者在项目类的方法声明部分删除
getVariables().add(变量)&
getbelies().add(信念)
//以及它们关联的变量声明和添加
//mappedBy外键约束meanId
@OneToMany(cascade=CascadeType.ALL,mappedBy=“meanId”)
//添加到变量声明部分
私人收藏是指收藏;
//并在getter/setter部分下添加以下方法
@XmlTransient
公共集合getMeansCollection(){
返回均值集合;
}
//在项目类构造函数中,对集合进行以下初始化
meansCollection=new ArrayList();
//现在你的电话变得简单了
平均值=新平均值();
平均值。设置变量(变量);
挫折信念(信念);
项目=新项目();
project.getMeansCollection().add(means);
projectDao.save(project);
//另外,看起来您应该使用@JoinColumns作为变量_id&
//信念id字段,其中每个变量实际上是一个类变量
//表示,而不是整数。在这种情况下,您的平均id为
//单个主键和类变量&confidence都作为@JoinColumn
//外键约束
//4个空间
我找到了问题的答案,我想我会把它贴出来,以防有人发现它有用
我所做的是将引用变量和信念实体设置为Mean实体时,将它们存储在MeanPK类本身中。我向MeanPk类中的ID获取程序添加了一些逻辑,这样当hibernate调用它们时,它将首先检查设置MeanPk类中存储的对象的ID。这是因为hibernate将在到达平均实体之前插入并持久化瞬态变量和信念实体,因为它是最底层的子实体。我的所有集合都有CascadeType.ALL,因此我不需要担心手动保存每个实体,Hibernate将把保存操作从父级级联到子级
以下是更新后的MeanPK类和Mean实体类:
@Entity
@Table(name = "mean")
public class Mean implements Serializable {
private static final long serialVersionUID = -5732898358425089380L;
// composite key
@EmbeddedId
private MeanPK pk = new MeanPK();
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
@JoinColumn(name = "belief_id", insertable = false, nullable = false, updatable = false)
private Belief belief;
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
@JoinColumn(name = "variable_id", insertable = false, nullable = false, updatable = false)
private Variable variable;
// more attributes excluded
public MeanPK getPk() {
return pk;
}
protected void setPk(MeanPK pk) {
this.pk = pk;
}
public Belief getBelief() {
return belief;
}
public void setBelief(Belief belief) {
pk.setBelief(this.belief = belief);
}
@XmlTransient
public Variable getVariable() {
return variable;
}
public void setVariable(Variable variable) {
pk.setVariable(this.variable = variable);
}
@Embeddable
public static class MeanPK implements Serializable {
private static final long serialVersionUID = 341373316515655834L;
@Access(AccessType.PROPERTY)
@Column(name = "belief_id", nullable = false, updatable = false)
protected Integer beliefId;
@Access(AccessType.PROPERTY)
@Column(name = "variable_id", nullable = false, updatable = false)
protected Integer variableId;
@Transient
private Belief belief;
@Transient
private Variable variable;
public Integer getBeliefId() {
if (beliefId == null && belief != null) {
beliefId = belief.getId();
}
return beliefId;
}
protected void setBeliefId(Integer beliefId) {
this.beliefId = beliefId;
}
public Belief getBelief() {
return belief;
}
void setBelief(Belief belief) {
this.belief = belief;
if (belief != null) {
beliefId = belief.getId();
}
}
public Integer getVariableId() {
if (variableId == null && variable != null) {
variableId = variable.getId();
}
return variableId;
}
protected void setVariableId(Integer variableId) {
this.variableId = variableId;
}
public Variable getVariable() {
return variable;
}
void setVariable(Variable variable) {
this.variable = variable;
if (variable != null) {
variableId = variable.getId();
}
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof MeanPK)) {
return false;
}
MeanPK other = (MeanPK) obj;
return getBeliefId().equals(other.getBeliefId()) && getVariableId().equals(other.getVariableId());
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(getBeliefId()).append(getVariableId()).toHashCode();
}
}
}
是的,这是暂时的
那么你是这样打电话的
MeanPK MeanPK=新的MeanPK(variableId,beliefId)
打这个电话时这对你有用吗
平均值=新平均值(变量ID,beliefId) 欢迎来到堆栈溢出!谢谢你的回答,但请让它更具解释性,最好是显示OP在哪里进行更改。
@Entity
@Table(name = "mean")
public class Mean implements Serializable {
private static final long serialVersionUID = -5732898358425089380L;
// composite key
@EmbeddedId
private MeanPK pk = new MeanPK();
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
@JoinColumn(name = "belief_id", insertable = false, nullable = false, updatable = false)
private Belief belief;
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
@JoinColumn(name = "variable_id", insertable = false, nullable = false, updatable = false)
private Variable variable;
// more attributes excluded
public MeanPK getPk() {
return pk;
}
protected void setPk(MeanPK pk) {
this.pk = pk;
}
public Belief getBelief() {
return belief;
}
public void setBelief(Belief belief) {
pk.setBelief(this.belief = belief);
}
@XmlTransient
public Variable getVariable() {
return variable;
}
public void setVariable(Variable variable) {
pk.setVariable(this.variable = variable);
}
@Embeddable
public static class MeanPK implements Serializable {
private static final long serialVersionUID = 341373316515655834L;
@Access(AccessType.PROPERTY)
@Column(name = "belief_id", nullable = false, updatable = false)
protected Integer beliefId;
@Access(AccessType.PROPERTY)
@Column(name = "variable_id", nullable = false, updatable = false)
protected Integer variableId;
@Transient
private Belief belief;
@Transient
private Variable variable;
public Integer getBeliefId() {
if (beliefId == null && belief != null) {
beliefId = belief.getId();
}
return beliefId;
}
protected void setBeliefId(Integer beliefId) {
this.beliefId = beliefId;
}
public Belief getBelief() {
return belief;
}
void setBelief(Belief belief) {
this.belief = belief;
if (belief != null) {
beliefId = belief.getId();
}
}
public Integer getVariableId() {
if (variableId == null && variable != null) {
variableId = variable.getId();
}
return variableId;
}
protected void setVariableId(Integer variableId) {
this.variableId = variableId;
}
public Variable getVariable() {
return variable;
}
void setVariable(Variable variable) {
this.variable = variable;
if (variable != null) {
variableId = variable.getId();
}
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof MeanPK)) {
return false;
}
MeanPK other = (MeanPK) obj;
return getBeliefId().equals(other.getBeliefId()) && getVariableId().equals(other.getVariableId());
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(getBeliefId()).append(getVariableId()).toHashCode();
}
}
}