2015-11-27 32 views
0

我有一個錯誤讓我發瘋。當我嘗試創建一個新對象時,Hibernate會返回一個錯誤:當從數據庫加載對象時發生TransientObjectException

對象引用未保存的瞬態實例 - 保存沖洗前的瞬態實例:EquipmentType;嵌套的例外是org.hibernate.TransientObjectException:對象引用一個未保存的瞬態的實例 - 保存瞬態實例之前

我有以下Spring服務:

CommandService

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

EquipmentService

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

對於型號和EquipmentType,那些方法沒有明確定義。

你能幫我弄清楚爲什麼當我打電話給createCommand(..)時返回這個錯誤嗎?

+0

你是如何爲模型類定義equals()和hashcode()方法的?你可以添加那些問題的細節。 – Mohit

+0

@mohit我編輯了我原來的帖子。請注意,'EqualsBuilder'由Apache Commons提供。 – dounyy

回答

1

我認爲問題在於您在getEquipment方法中設置了新的EquipmentTypeModel。由於您尚未在這兩個類中定義equals()和hashcode方法,因此hibernate無法將它們與已存在的對象進行比較。它將它們視爲分離的(因爲equals()和hashcode()方法指示新對象而不是現有對象)。這就是爲什麼它首先要求您節省設備類型和模型對象。

我認爲你應該在設備類型&模型中正確覆蓋equals()& hashcode()。


編輯

我想你不應該添加爲您在completeType再次重寫它()方法新EquipmentType。爲什麼你不改變你的API來

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

如果你不能改變的API,你將有被觸發休眠刷新之前,先堅持新的類型和型號。

+0

但我的'equals()'方法會比較這些對象的ID。在'getEquipment()'中,我的對象沒有任何ID,所以它們仍然被認爲是分離的,對嗎? – dounyy

+1

新對象保持分離狀態,因爲在觸發刷新之前您沒有保存它們。只要執行選擇查詢,刷新就會自動觸發。我編輯了答案以提供解決方法。 – Mohit

+0

我不明白的是,如果事務沒有結束,爲什麼hibernate必須刷新? – dounyy

相關問題