ไฮเบอร์เนตลบวัตถุลูกหลังจาก session.update (พาเรนต์)

ฉันมีความสัมพันธ์ระหว่างพ่อแม่และลูกที่เรียบง่ายมากระหว่างวัตถุประเภท "โฟลเดอร์" ซึ่งมีลักษณะดังนี้:

  • โฟลเดอร์สามารถมีโฟลเดอร์หลักได้ 0-1 โฟลเดอร์
  • โฟลเดอร์สามารถมีโฟลเดอร์ย่อยได้ 0-n (โฟลเดอร์ย่อย)

โดยพื้นฐานแล้วเวอร์ชันที่เรียบง่ายของโฟลเดอร์คลาส Java จะมีลักษณะดังนี้:

public class Folder{
    long id;
    Set<Folder> childFolders;
    Folder parentFolder;
    String path;

    // Getter, setter and other (for this question)
    // not relevant properties omitted

    public boolean equals(Object obj){
            if (obj == null) return false;
            if (obj == this) return true;
            if (obj instanceof Folder){
                    Folder folder = (Folder)obj;
                    return folder.getPath().equals(getPath());
            }
            return false;
    }

    public int hashCode(){
            return getPath().hashCode();
    }

}

ลำดับชั้นการทดสอบอย่างง่ายของฉันมีลักษณะดังนี้:

  folder1
  folder2
- folder3
   subfolder3-1

เมื่อใช้ Hibernate ฉันโทร:

session.update(folder1);
session.update(folder2);
session.update(folder3);

การโทรสองครั้งแรกสำเร็จ

การเรียกครั้งสุดท้ายสำหรับโฟลเดอร์ 3 ไม่มีข้อยกเว้น แต่จะลบโฟลเดอร์ย่อย 3-1 ออกจากชุด "childFolders" ภายในของโฟลเดอร์ 3 นั่นหมายความว่า folder3.childFolders.size() = 0 แม้ว่าจะเป็น 1 ก่อนการโทรอัปเดตครั้งล่าสุดก็ตาม ข้อสำคัญ: ในฐานข้อมูล โฟลเดอร์ "subfolder3-1" ยังคงมีอยู่!

เป็นไปได้ยังไง?

นี่คือไฟล์การแมปของฉัน:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="test.Folder" table="FOLDERS">

        <id name="id" type="long" access="field">
            <column name="FOLDER_ID" />
            <generator class="native" />
        </id>     

        <set name="childFolders" table="FOLDERS" inverse="true" cascade="save-update">
            <key column="PARENT_FOLDER_ID"></key>
            <one-to-many class="test.Folder" />
        </set>

        <many-to-one name="parentFolder" column="PARENT_FOLDER_ID" />

        <property name="path" column="FOLDER_PATH" />
    </class>
</hibernate-mapping>

person Timo Ernst    schedule 01.06.2011    source แหล่งที่มา
comment
วิธีการ equals() และ hashcode() ใน test.Folder มีลักษณะอย่างไร   -  person matt b    schedule 02.06.2011
comment
@matt b ฉันเพิ่มสองวิธีในโพสต์ต้นฉบับ   -  person Timo Ernst    schedule 02.06.2011


คำตอบ (3)


ฉันคิดว่าปัญหาอยู่ในแอตทริบิวต์ inverse="true": คุณลักษณะผกผันจะไม่ถูกบันทึก

person Maurice Perry    schedule 01.06.2011
comment
หืม การตั้งค่า inverse=false ไม่สามารถแก้ไขปัญหาได้ นอกจากนั้น: การโทร session.save(folder3) ทำงานได้อย่างสมบูรณ์ - person Timo Ernst; 02.06.2011

ตรวจสอบให้แน่ใจว่าคุณสร้างลิงก์อย่างถูกต้องในโลกของ Java

  folder3.getChildFolders().add(subfolder3);
  subfolder3.setParent(folder3);
  session.persist(folder3); //cascade here will save subfolder3

นี่คือเอกสารประกอบการไฮเบอร์เนต

person zmf    schedule 01.06.2011
comment
ก่อนที่ฉันจะเรียกใช้เมธอด session.update(..) ที่โพสต์ด้านบน โฟลเดอร์ทั้งหมดยังคงอยู่อยู่แล้ว! ดังนั้นฉันจึงเรียก session.update(..) ในโฟลเดอร์ถาวร เพื่อที่จะแทรกโฟลเดอร์ลงในฐานข้อมูล (เป็นครั้งแรก) ฉันใช้ session.save.(folder3) (ซึ่งทำงานได้อย่างสมบูรณ์แบบ) แทน session.persist(folder3) มันผิดเหรอ? - person Timo Ernst; 02.06.2011
comment
ในโค้ดที่แทรกโฟลเดอร์ลงในฐานข้อมูลในตอนแรก คุณจะเพิ่มโฟลเดอร์ไปยังพาเรนต์ด้วยหรือไม่ (ดังที่ @zmf แสดงด้านบน) - person RMorrisey; 02.06.2011
comment
@RMorrisey ใช่ฉันทำ ฉันยังพิมพ์ต้นไม้ด้วย (รวมถึง id และชื่อของพาเรนต์) หนึ่งครั้งก่อนและอีกครั้งหลังการโทร session.update(folder3) ก่อนที่ session.update(folder3) ทุกอย่างจะเป็นอย่างที่ควรจะเป็น (โฟลเดอร์ย่อย3-1 มีรหัสและการอ้างอิงถึงพาเรนต์) หลังจากการเรียกอัพเดต โฟลเดอร์ย่อย 3-1 หายไป - person Timo Ernst; 02.06.2011
comment
@valmar โทร update() ไม่ควรลบการเชื่อมโยงนั้นนั่นจะเป็น 'แปลก' หลังจากที่คุณโทรไปที่ session.update(folder3) เนื้อหาของฐานข้อมูลถูกต้องหรือไม่? ถ้าเป็นเช่นนั้นถ้าคุณพูดว่า Folder f3 = session.get(folder3); ทำ f3.childFolders.size() == 0; ? คุณสามารถเพิ่มโค้ดเพิ่มเติมได้ไหม บางทีการทดสอบที่คุณคงโฟลเดอร์เหล่านี้ไว้อาจเป็นการเริ่มต้นที่ดี แผนที่ของคุณดูถูกต้องสำหรับฉัน - person zmf; 02.06.2011
comment
ในที่สุดฉันก็พบสาเหตุของปัญหา คำแนะนำของคุณในการตรวจสอบ folder3.childFolders.size() ชี้ให้ฉันไปในทิศทางที่ถูกต้อง ฉันมี folder3.childFolders.clear() อยู่ที่ตำแหน่งที่ซ่อนอยู่ในโค้ด ดังนั้น `folder3.childFolders.size() จึงเป็น 0 เสมอ ขอบคุณสำหรับความช่วยเหลือของคุณ! - person Timo Ernst; 03.06.2011

ฉันเพิ่มโค้ดแก้ไขข้อบกพร่องเพิ่มเติม และในที่สุดฉันก็พบวิธีแก้ไข: ก่อนการโทร session.update(folder3) ฉันมีการเรียก folder.childFolders.clear() ที่ซ่อนอยู่เล็กๆ น้อยๆ ซึ่งทำให้เกิดปัญหาอย่างเห็นได้ชัด ดังนั้นปัญหาจึงไม่เกี่ยวข้องกับ Hibernate เลย ด้วยความโง่เขลาของฉันเท่านั้น ขออภัยทุกคนที่รบกวนและขอบคุณมากสำหรับความช่วยเหลือ!

person Timo Ernst    schedule 02.06.2011