2012-12-15 53 views
0

休眠V.4.1.8最終SaveOrUpdate跳過表

春:3.1.3發佈

場景:在客戶註冊過程中,用戶將填寫完整。在完成表格之前,他可以多次保存表格並點擊提交以完成內容。應用程序僅在最終提交後纔會創建客戶ID。 爲了實現這個功能,我創建了兩個基於相同POJO的表。 Ref:Mapping same POJO to more than one table

問題:將數據保存到客戶表中。 hibernate將記錄插入地址表中並直接插入族表,但忽略客戶表。因此拋出異常:無法添加或更新子行:外鍵約束失敗

請將看到sql序列中的custDetail對象放入備份表和客戶表中。

插入到備份表

Hibernate: insert into mypack.address_bk (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: insert into mypack.address_bk (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: insert into mypack.address_bk (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: insert into mypack.customer_bk (version, custId, custBirthDate, custEducation, custFirstName, custGender, custLastName, custMiddleName, custTitle, exServiceManFlag, fatherFullName, handicappedFlag, motherFullName, staffFlag, status, userId, bankCode, branchCode, customerPhoto, currentAddress, permanentAddress, officeAddress) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: insert into mypack.family_bk (custId, memberName, relation, birthDate, gender, occupation) values (?, ?, ?, ?, ?, ?) 

插入到客戶表

Hibernate: insert into mypack.address (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: insert into mypack.address (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: insert into mypack.address (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: insert into mypack.family (custId, memberName, relation, birthDate, gender, occupation) values (?, ?, ?, ?, ?, ?) 
SQL Error: 1452, SQLState: 23000 Cannot add or update a child row: a foreign key constraint fails 

表認定中:

<class entity-name="com.boss.mypack.model.Customer" lazy="true" 
    name="com.boss.mypack.model.Customer" polymorphism="explicit" 
    schema="mypack" table="customer"> 
    <id length="15" name="custId" type="string"> 
     <column length="20" name="custId" /> 
     <generator class="assigned" /> 
    </id> 
    <version column="version" generated="never" name="version" 
     type="integer" unsaved-value="null" /> 
    <property generated="never" lazy="false" name="tempId" type="java.lang.Integer"> 
     <column name="tempId" not-null="false" /> 
    </property> 
    <many-to-one cascade="all" class="com.boss.mypack.model.Address" 
     entity-name="com.boss.mypack.model.Address" fetch="select" lazy="false" 
     name="OfficeAddress"> 
     <column name="officeAddress" /> 
    </many-to-one> 
    <set cascade="all" fetch="select" inverse="true" lazy="true" name="family" 
     sort="unsorted" table="family"> 
     <key> 
      <column length="20" name="custId" /> 
     </key> 
     <one-to-many class="com.boss.mypack.model.Family" 
      entity-name="com.boss.mypack.model.Family" /> 
    </set> 
</class> 

回表:

<class entity-name="bkCustomer" lazy="true" 
    name="com.boss.mypack.model.Customer" polymorphism="explicit" 
    schema="mypack" table="customer_bk"> 
    <id length="4" name="tempId" type="java.lang.Integer"> 
     <column length="20" name="tempId" /> 
     <generator class="identity" /> 
    </id> 
    <version column="version" generated="never" name="version" 
     type="integer" unsaved-value="null" /> 
    <property generated="never" lazy="false" name="custId" type="string"> 
     <column length="20" name="custId" /> 
    </property> 
    <many-to-one cascade="all" class="com.boss.mypack.model.Address" 
     entity-name="bkAddress" fetch="select" lazy="false" name="OfficeAddress"> 
     <column name="officeAddress" /> 
    </many-to-one> 
    <set cascade="all" fetch="select" inverse="true" lazy="true" name="family" 
     sort="unsorted" table="bkfamily"> 
     <key> 
      <column length="20" name="custId" /> 
     </key> 
     <one-to-many class="com.boss.mypack.model.Family" 
      entity-name="bkFamily" /> 
    </set> 
</class> 

保存方法:

public void saveCustomer(Customer custDetails) { 
    Session session; 
    session = getSessionFactory().getCurrentSession(); 
    session.beginTransaction(); 

    try { 
     session.saveOrUpdate("bkCustomer", custDetails); 
     session.getTransaction().commit(); 
    } catch (Exception e) { 
     session.getTransaction().rollback(); 
     e.printStackTrace(); 
    } 
} 

批准客戶的方法

@Override 
public void approveCustomer(Customer custDetails) { 
    Session session = null; 
    // Saving Customer details to Database 
    try { 
     //TODO:Need to this in single session, In failure, every changes should get rolled back. 
     //Removing from backup Table 
     session = getSessionFactory().getCurrentSession(); 
     session.beginTransaction(); 
     session.delete("bkCustomer", custDetails); 
     session.getTransaction().commit(); 
     System.out.println("**** Record Deleted ****"); 

     session = getSessionFactory().getCurrentSession(); 
     session.beginTransaction(); 

     // check to see whether this is new customer. 
     if (custDetails.getCustId() == null) { 
      // New Customer - Generate Customer ID 
      custDetails.setTempId(null); 
      custDetails.setCustId(getNextCustomerCode(session)); 

      // Clear all Auto Generated IDs 
      custDetails.getCurrentAddress().setAddressId(null); 
      custDetails.getOfficeAddress().setAddressId(null); 
      custDetails.getPermanentAddress().setAddressId(null); 
      // custDetails.getPhotoMaster().setPhotoId(0); 

      Set<Family> familyMembers = custDetails.getFamily(); 

      for (Family member : familyMembers) { 
       member.setMemberId(null); 
      } 
     } else { 
      System.out.println("**** This customer is already present in Database"); 
     } 

     custDetails.setStatus("A"); 

     session.saveOrUpdate("com.boss.mypack.model.Customer", custDetails); 

     //Following works properly, updates Backup tables 
     //session.saveOrUpdate("bkCustomer", custDetails); 

     session.getTransaction().commit(); 

     // Saving Customer details to LDAP. 
     // ldapDAO.saveOrUpdate(custDetails); 
     // session.getTransaction().commit(); 
    } catch (Exception e) { 
     session.getTransaction().rollback(); 
     e.printStackTrace(); 
    } 
} 

我沒有得到客戶的表中的任何異常。我試圖使用session.clear/flash/evict/merge/replicate等來分離對象,使用DOZER但沒有進展。即使我試圖刪除級聯選項。

我不確定它出錯的地方。請幫忙。

問候,

希裏什

回答

0

是你的直接約束?讓他們延期。這樣,hibernate可以在事務結束之前寫入所有表而不會受到約束違規。

如果您正在使用MySQL,則無法將約束推遲到事務結束。然後你必須確保你總是在數據庫中插入一致的狀態。對於你來說,這意味着重寫一些代碼,以便有效地發出兩次保存,一次只保存客戶,另一次保存客戶的家庭屬性。

無論如何,發現Hibernate試圖首先插入系列的原因很有趣,而在bk表中,插入順序與預期相同。只是一個猜測:嘗試移動的聲明

custDetails.setStatus("A"); 

if塊

// check to see whether this is new customer. 
    if (custDetails.getCustId() == null) { 
     // New Customer - Generate Customer ID 
     custDetails.setTempId(null); 
     custDetails.setCustId(getNextCustomerCode(session)); 

     // Clear all Auto Generated IDs 
     custDetails.getCurrentAddress().setAddressId(null); 
     custDetails.getOfficeAddress().setAddressId(null); 
     custDetails.getPer... 

這樣上面,那麼Hibernate可能會重新排序插入,因爲家庭是最後編輯的實體,您的代碼將工作。無論如何,這會嚴重依賴於Hibernate內部。如前所述,我建議使用兩次保存。