gpt4 book ai didi

java - Hibernate - 使用生成的复合键插入临时子实体

转载 作者:行者123 更新时间:2023-11-30 11:08:24 26 4
gpt4 key购买 nike

我在使用 Hibernate 插入一堆临时子实体时遇到问题,这些临时子实体可能具有由其他临时子实体组成的复合键,方法是保存分离的父实体。我很确定我的复合键类设置正确,但每次我尝试保存具有 transient 实体(尚未生成 ID)的父实体时,我都会收到此错误:

org.hibernate.id.IdentifierGenerationException: null id generated for:class org._.website.data.entity.Mean

所以 Hibernate 从不生成 Composite 键,我认为它应该能够给出被引用的属性。但是,由于复合键引用的属性也是暂时的,因此没有 ID 可用于手动设置复合键。所以我希望 Hibernate 足够聪明,可以自己生成。

有没有办法让 Hibernate 处理带有引用其他 transient 子实体的复合键的 transient 子实体的保存/插入?

这是我正在使用的代码。如果在 projectDao.save(project) 上失败;

Variable variable = new Variable();
variable.setProject(project);
variable.setName("x");

Belief belief = new Belief();
belief.setProject(project);
belief.setName("model-1");

Mean mean = new Mean();
mean.setVariable(variable);
mean.setBelief(belief);

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

如果有帮助,这里是 Embeddable 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();
}

}

如果绝对必要,我可以先保存复合键引用的 transient 实体以获取 ID 并手动构建 MeanPK 复合键,但我希望 Hibernate 能够通过单个调用 projectDao.save(...);

感谢您的帮助!

最佳答案

我想出了我的问题的答案,我想我会发布它以防有人发现它有用。

我所做的是在将引用的 Variable 和 Belief 实体设置为 Mean 实体时将它们存储在 MeanPK 类本身中。我向 MeanPk 类中的 ID getter 添加了一些逻辑,以便当它们被 hibernate 调用时,它将首先检查以设置存储在 MeanPK 类中的对象的 id。这是有效的,因为 hibernate 将在到达 Mean 实体之前插入并保留 transient Variable 和 Belief 实体,因为它是最底层的子实体。我的所有集合都有 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();
}

}

}

关于java - Hibernate - 使用生成的复合键插入临时子实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28574927/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com