2009-12-15 120 views
0

假設這些都是我的父母和我的子對象:Hibernate的級聯刪除不工作

家長:

@Entity 
@Table(name = "import_table") 
public class ImportTable { 
    @Cascade({ CascadeType.ALL, CascadeType.DELETE_ORPHAN }) 
    @OneToMany(
     mappedBy = "table", 
     fetch = FetchType.EAGER 
    ) 
    public List<ImportTableColumn> getColumns() 
    { 
     return columns; 
    } 
    ... setter is defined but I don't think it's important for the example 
} 

兒童:

@Entity 
@Table(name = "import_table_column") 
public class ImportTableColumn { 
    @ManyToOne 
    @JoinColumn(
     name = "import_table_name", 
     nullable = false 
    ) 
    public ImportTable getTable() 
    { 
     return table; 
    } 
} 

以下僞代碼將起作用

  • 創建ImportTable實例,添加2列,創建會話,保存它,關閉會話;
  • 在不同的會話中讀取保存的實例,刪除一列;
  • 將它保存在另一個會話中;
  • 檢查列數等於1。

但下面的不會起作用:

  • 創建ImportTable的情況下,增加2列,創建一個會話,保存,關閉會話;
  • 在不同的會話中讀取保存的實例;
  • 手動重新創建保存的對象;
  • 刪除列;
  • 將它保存在另一個會話中;
  • 檢查列數等於1。

原因是我們有一個Java服務器/ Flex客戶端應用程序,我們需要加載對象,將它發送到客戶端,讓客戶端做它必須做的任何事情,將對象發回到服務器,然後保存它。

我認爲當我重新創建對象時,Hibernate正在迷失。據我所知,當從數據庫中檢索到對象時,Hibernate確實在對象中注入了一些東西。當我重新創建對象時,我不會複製對象類中不是已聲明字段的任何內容。這是重新創建對象的代碼(用於我的單元測試):

private ImportTable recreate(ImportTable original) throws IOException 
{ 
    final ImportTable copy = new ImportTable(); 
    copy.setDatabaseTableName(original.getDatabaseTableName()); 
    copy.setDisplayTableName(original.getDisplayTableName()); 
    if(original.getColumns() != null) { 
     copy.setColumns(new ArrayList<ImportTableColumn>(original.getColumns().size())); 
     for(ImportTableColumn originalColumn : original.getColumns()) { 
      final ImportTableColumn copyColumn = new ImportTableColumn(); 
      copyColumn.setTable(copy); 
      copyColumn.setDatabaseColumnName(originalColumn.getDatabaseColumnName()); 
      copyColumn.setDatatype(originalColumn.getDatatype()); 
      copyColumn.setExcelColumnName(originalColumn.getExcelColumnName()); 
      copyColumn.setId(originalColumn.getId()); 
      copyColumn.setLength(originalColumn.getLength()); 
      copyColumn.setPk(originalColumn.isPk()); 
      copyColumn.setRequired(originalColumn.isRequired()); 
      copyColumn.setPrecision(originalColumn.getPrecision()); 
      copy.getColumns().add(copyColumn); 
     } 
    } 
    return copy; 
} 

我相信當我重新創建對象時,hibernate會丟失。我想讓hibernate做的是將數據庫中的內容與對象中的內容進行比較,並僅保存差異。有沒有辦法做到這一點?

回答

2

當擁有者實體第一次連接到會話時,Hibernate將收集實例包裝到AbstractPersistentCollection的適當子類中。

PersistentCollection然後跟蹤刪除的收集元素;沒有它,Hibernate將只能夠對它們執行插入/更新(在大多數情況下;對於某些id生成器類,即使這是不可能的)。

你基本上運氣不好;您唯一能做的就是從數據庫中加載一個現有實體(ImportTable)並對其進行修改(例如,刪除已加載副本中但不在克隆中的集合元素),然後保存它。我不太瞭解爲什麼你需要首先克隆你的實體(我不知道Flex ...你是否將實體編組爲XML/JSON/etc?)所有PersistentCollection實現是Serializable,因此可以通過電線發送並返回。有一些方法可以將它們組裝到XML中,並返回。

+0

flex引擎(flex.messaging)不會序列化對象,我相信引擎使用反射來讀取字段,然後它使用自己的與flex客戶端兼容的序列化引擎。我只是檢查源代碼,當列表從客戶端返回時,引擎創建一個ArrayList來保存其內容。 我想我必須自己實施解決方案。我可以使用反射(通過commons-bean)讀取所有對象獲取器,找出是否有任何列表,然後讀取數據庫並使用其中的hibernate註釋比較列表id。 – 2009-12-15 04:19:55

+0

通過閱讀@Id註釋。我將評估這種情況是否會經常發生,足以證明額外的編碼,否則我可能會在對象本身手動執行此操作。 – 2009-12-15 04:22:04