2012-11-16 24 views
2

我有兩個objs; DocumentDocumentBatch休眠在列表中保存新元素而不刪除舊元素

文獻

public class Document implements Serializable { 

.... 
private String documentId; 
private DocumentBatch documentBatch; 
....} 

DocumentBatch

public class DocumentBatch implements Serializable { 


private String batchId; 

private List<Document> lDocuments = new LinkedList<Document>(); 
....} 

休眠映射:

<class name="Document" table="DOCUMENTS"> 
    ..... 
    <id name="documentID" column="DOCUMENT_ID" type="string" /> 
    <many-to-one name="documentBatch" class="DocumentBatch" not-null="false" 
    cascade="save-update" lazy="false" insert="false" update="false"> 
     <column name="BATCH_ID" not-null="true" /> 
    </many-to-one> 
    ...... 
</class> 


<class name="DocumentBatch" table="DOCUMENT_BATCHES"> 
    <id name="batchId" column="BATCH_ID" type="string" /> 
    <list name="lDocuments" table="DOCUMENTS" cascade="all" 
     inverse="false" lazy="false" mutable="true"> 
     <key not-null="true"> 
      <column name="BATCH_ID" /> 
     </key> 
     <list-index column="LIST_INDEX" base="0" /> 
     <one-to-many class="Document" /> 
     </list> 
    ...... 
</class> 

DocumentBatch有一個Document的列表,每次我運行我的測試用例並使用session.saveOrUpdate(documentBatch)來更新DocumentBatch對象具有相同的主鍵,但新生成的文檔對象列表(所有對象都是新生成的)。

休眠將更新DocumentBatch與索引保存全新的文檔列表,但不刪除列表中的舊元素。

所以當我運行我的測試用例兩次,每次列表文檔有5 Obj,我將有最後10個objs。兩個索引= 0,兩個索引= 1等。

所以它不更新列表,但只保存新的。舊列表的元素可以在數據庫中找到。當我嘗試獲得DocumentBatch, DocumentBatch時,有一箇舊對象列表。

我該如何解決這個問題?哪裏有錯誤?非常感謝。

更新1:UnitTestCase

@Test 
public void testSaveDocumentBatch() throws Throwable { 
.... 
String batchId = "500700"; 
DocumentBatch documentBatch = new DocumentBatch(batchId, name); 
    .... 
    for (int i = 0; i < 5; i++) { 
    String documentID = SessionIdentfierGenerator.nextSessionId();//generatting Id 
    Document document = new Document(documentID); 
    documentBatch.insertDocument(document); 
} 
    .... 
    session.saveOrUpdate(documentBatch); 
    ....} 

和了Methode insertDocument(文檔文件)在類DocumentBatch:

public class DocumentBath{ 
..... 
private List<Document> lDocuments = new LinkedList<Document>(); 
..... 
public void insertDocument(Document document) { 
    lDocuments.add(document); // lDocuments is a list DocumentBatch 
    document.setDocumentBatch(this); 
} 
.....} 

更新2:Oracle數據庫腳本:

文檔的

CREATE TABLE DOCUMENTS(
DOCUMENT_ID VARCHAR2(255 CHAR) NOT NULL, 
BATCH_ID VARCHAR2(255 CHAR) NOT NULL, 
...); 


CREATE UNIQUE INDEX PK_DOCUMENT ON DOCUMENTS (DOCUMENT_ID); 
ALTER TABLE DOCUMENTS ADD (CONSTRAINT PK_DOCUMENT PRIMARY KEY (DOCUMENT_ID) USING INDEX PK_DOCUMENT); 

ALTER TABLE DOCUMENTS ADD (CONSTRAINT FK_DOCUMENT_BATCH_ID FOREIGN KEY (BATCH_ID) REFERENCES DOCUMENT_BATCHES (BATCH_ID) ON DELETE CASCADE); 

中DocumentBatch

CREATE TABLE DOCUMENT_BATCHES(
BATCH_ID VARCHAR2(255 CHAR)  NOT NULL 
...); 

ALTER TABLE DOCUMENT_BATCHES ADD (
PRIMARY KEY (BATCH_ID)); 
+1

您可以在調用saveOrUpdate之前提供代碼提取或創建documentBatch。需要檢查documentBatch對象是從數據庫中提取還是每次使用相同的id新創建? –

+0

感謝您的快速回復。我剛更新了原文。 –

+0

從類別DocumentBatch中的列表obj - 私人列表 lDocuments = new LinkedList (); –

回答

0

你去那裏。在你的測試案例中,你正在爲DB中已經存在的實體創建新的實體對象。這混淆了休眠&休眠不會刪除現有文檔。

String batchId = "500700"; 
    DocumentBatch documentBatch = new DocumentBatch(batchId, name); 

而是這個 「新DocumentBatch(batchId,名)」,第一次使用的get()或load()的通過ID 500700.一旦你獲取現有對象,然後執行以下步驟獲取現有DocumentBatch對象。

1)創建一個方法,例如clearExistingDocuments()。在此方法中,首先迭代文件列表&,使BATCH_ID爲空。一旦迭代完成,然後從列表中刪除所有這些文件。

2)現在在同一個空列表中添加新創建的文檔。避免創建新的列表實例。使用相同的空列表實例&添加新文檔。

這應該解決問題。由於這些步驟,hibernate將會知道最初有一些現有值&現在它們被明確地刪除,所以hibernate會觸發相關的刪除查詢。如果需要,也可以使用孤立刪除。這將刪除孤兒的對象而不是將它們保存在文檔表中。

+0

你的答案很自然。你知道我可以說服Hibernate相信新創建的帶有Id 500700的DocumentBatch是數據庫中的DocumentBatch,但沒有它的文檔列表。所以如果有人只是創建一個新的DocumentBatch而不詢問它是否已經存在,那麼它將是不安全的。 –