Hibernate在列表中保存新元素而不删除旧元素

时间:2012-11-16 11:36:00

标签: java hibernate list

我有两个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>();
....}

Hibernate 映射:

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

DocumentBatchDocument列表,每次运行我的测试用例并使用session.saveOrUpdate(documentBatch)更新DocumentBatch对象时使用相同的主键,但使用新生成的Document列表对象(所有对象都是新生成的。)。

Hibernate将更新DocumentBatch并保存包含索引的全新文档列表,但不删除列表中的旧元素。

所以当我运行我的测试用例两次并且每次 Document 的列表都有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);
    ....}

Class DocumentBatch中的Methode insertDocument(Document document):

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 个答案:

答案 0 :(得分:0)

你去吧。在您的测试用例中,您正在为DB中已存在的实体创建新的实体对象。这会混淆休眠&amp; hibernate不会删除现有文档。

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

而不是这个“new DocumentBatch(batchId,name)”,首先使用get()或load()来获取id为500700的现有DocumentBatch对象。获取现有对象后,请执行以下步骤。

1)创建一个方法,例如clearExistingDocuments()。在这种方法中,首先迭代文档列表&amp;使BATCH_ID为空。迭代完成后,从列表中删除所有这些文档。

2)现在将新创建的文档添加到同一个空列表中。避免创建新的列表实例。使用相同的空列表实例&amp;添加新文件。

应该解决这个问题。由于这些步骤,hibernate将知道最初存在一些现有值和&amp;现在那些被明确删除,所以hibernate将触发相关的删除查询。如果需要,也可以使用orphan-delete。这将删除孤立的DOcument对象,而不是将它们保存在文档表中。