gpt4 book ai didi

java - 从数据库加载对象时发生 TransientObjectException

转载 作者:行者123 更新时间:2023-12-01 10:50:21 26 4
gpt4 key购买 nike

我有一个错误让我发疯。当我尝试创建新对象时,Hibernate 返回错误:

object references an unsaved transient instance - save the transient instance before flushing: EquipmentType; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before

我有以下 Spring 服务:

命令服务

public class CommandService implements ICommandService {
@Override
public Command createCommand(String name, String eqpName) {
Command cmd = new Command();
Equipment eqp = getEquipment(eqpName);

cmd.setEquipment(eqp);
cmd.setName(name);

return cmd;
}

@Override
public Equipment getEquipment(String eqpName) {
IEquipmentService eqpService = (IEquipmentService) SPRING_CONTEXT.getBean("EquipmentService");

Equipment eqp = eqpService.findEquipmentByName(eqpName);

EquipmentType eqpType = new EquipmentType();
eqpType.setName("MyType");
eqp.setType(eqpType);

Model model = new Model();
model.setName("MyModel");
eqp.setModel(model);

eqpService.saveEquipment(eqp);

return eqp;
}
}

设备服务

public class EquipmentService implements IEquipmentService {

private DAO dao; // This DAO is autowired

@Override
public void saveEquipment(Equipment eqp) {
completeModel(eqp);
completeEqpType(eqp);

((EquipmentDAO) dao).merge(eqp);
}

private void completeModel(Equipment eqp) {
IModelService modelService = (IModelService) SPRING_CONTEXT.getBean("ModelService");
Model result = modelService.findModelByName(eqp.getModel().getName()); // Fails here

eqp.setModel(result);
}

private void completeEqpType(Equipment eqp) {
IEquipmentTypeService eqpTypeService = (IEquipmentTypeService) SPRING_CONTEXT.getBean("EquipmentTypeService");
EquipmentType result = eqpTypeService.findEquipmentTypeByName(eqp.getType().getName());

eqp.setType(result);
}
}

请注意,IEquipmentServiceICommandService 的所有方法都配置为事务性的。我的对象 EquipmentModelEquipmentType 组成。这些对象引用数据库中已经创建的对象,这就是为什么我不想再次保存它们。

这是 Hibernate 配置:

<class name="Equipment" table="equipment" lazy="false">
<id name="equipmentId" type="java.lang.Integer">
<column name="EQUIPMENT_ID" />
<generator class="native" />
</id>
<many-to-one name="type" class="EquipmentType" fetch="join" not-null="true">
<column name="TYPE_ID" not-null="true" />
</many-to-one>
<many-to-one name="model" class="Model" fetch="join" not-null="true">
<column name="MODEL_ID" not-null="true" />
</many-to-one>
</class>

编辑:根据要求,这里是方法equals(..)hashcode(..)

对于设备

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((equipmentId == null) ? 0 : equipmentId.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((model == null) ? 0 : model.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}

if (obj instanceof Equipment) {
Equipment eqp = (Equipment) obj;
return new EqualsBuilder().append(this.equipmentId, eqp.getEquipmentId()).isEquals();
}

return false;
}

对于 Model 和 EquipmentType,这些方法没有明确定义。

你能帮我弄清楚为什么当我调用 createCommand(..) 时会返回此错误吗?

最佳答案

我认为问题在于您在 getEquipment 方法中设置了新的 EquipmentTypeModel 。由于您尚未在这两个类中定义 equals() 和 hashcode 方法,因此 hibernate 无法将它们与已持久化的对象进行比较。它将它们视为分离的(因为 equals() 和 hashcode() 方法指示新对象而不是现有对象)。这就是为什么它要求您首先保存设备类型和模型对象。

我认为您应该在 EquipmentType 和 Model 中正确重写 equals() 和 hashcode()。

<小时/>

编辑

我认为您不应该添加新的 EquipmentType,因为您在completeType() 方法中再次覆盖它。为什么不将 API 更改为

EquipmentService#saveEquipment(Equipment e, Sting type, String modelName){
EquipmentType t = findType();
Model m = findModel();
e.setType(t);
e.setModel(m);
}

如果您无法更改 API,则必须在触发 hibernate 刷新之前先保留新的类型和模型。

关于java - 从数据库加载对象时发生 TransientObjectException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33958470/

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