คำอธิบายประกอบ @OrderColumn ใน Hibernate 3.5.1

ฉันกำลังพยายามใช้คำอธิบายประกอบ @OrderColumn กับ Hibernate 3.5

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@OrderColumn(name = "pos")
private List<Children> childrenCollection;

เมื่อดึงข้อมูลทุกอย่างทำงานได้ดี แต่ฉันไม่สามารถจัดลำดับองค์ประกอบในรายการใหม่และบันทึกลำดับใหม่ลงในฐานข้อมูลได้


person Piotr Gwiazda    schedule 02.06.2010    source แหล่งที่มา
comment
คุณช่วยแสดงวิธีเรียงลำดับรายการใหม่และบันทึกกลับไปยังฐานข้อมูลได้ไหม ???   -  person Arthur Ronald    schedule 02.06.2010
comment
ฉันได้ลองสร้าง ArrayList ใหม่และ parent.setChildrenCollection(newList) ฉันได้ลอง Collections.sort ในรายการที่ดึงข้อมูลแล้ว ฉันได้ลองลบรายการว่างออกจากคอลเลกชันแล้ว ไม่มีอะไรเกิดขึ้น. การเปลี่ยนแปลงอื่นๆ ในพาเรนต์ถูกบันทึกลงในฐานข้อมูลแล้ว แต่ไม่มีอะไรเกิดขึ้นกับรายการ   -  person Piotr Gwiazda    schedule 07.06.2010
comment
ไม่ใช่ Hibernate 3.5 สำหรับ JPA 1.0 และ @OrderColumn คือ JPA 2.0!   -  person Neil Stockton    schedule 12.11.2015


คำตอบ (3)


การรวมกันของ @OneToMany(mappedBy="...") และ @OrderColumn ไม่ได้รับการสนับสนุนโดย Hibernate ปัญหา JIRA นี้ติดตามคำขอเพื่อแสดงข้อความแสดงข้อผิดพลาดที่ชัดเจนยิ่งขึ้นเมื่อใช้ชุดค่าผสมที่ไม่ถูกต้องนี้: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5390

ฉันคิดว่าสิ่งนี้ไม่ได้รับการสนับสนุนเนื่องจากเป็นรูปแบบความสัมพันธ์ที่แปลก คำอธิบายประกอบข้างต้นระบุว่าด้าน "หนึ่ง" ของความสัมพันธ์กำหนดว่าความสัมพันธ์จะถูกล้างไปยังฐานข้อมูลอย่างไร แต่ลำดับ/ตำแหน่งจะพร้อมใช้งานเฉพาะในด้าน "หลาย" โดยการตรวจสอบรายการ มันสมเหตุสมผลมากกว่าสำหรับฝ่าย "หลายฝ่าย" ที่จะเป็นเจ้าของความสัมพันธ์ เนื่องจากฝ่ายนั้นรู้เกี่ยวกับทั้งความเป็นสมาชิกและการเรียงลำดับขององค์ประกอบ

เอกสารคำอธิบายประกอบ Hibernate อธิบายสถานการณ์นี้โดยละเอียด:

http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-collection-extratype-indexbidir

วิธีแก้ปัญหาคือการลบแอตทริบิวต์ "mappedBy" ซึ่งจะทำให้การเชื่อมโยงใช้กลยุทธ์ตารางรวมเริ่มต้นแทนคอลัมน์ในตารางเป้าหมาย คุณสามารถระบุชื่อของตารางเข้าร่วมได้โดยใช้คำอธิบายประกอบ @JoinTable

ผลสุทธิของการเปลี่ยนแปลงนี้คือด้าน "กลุ่ม" ของความสัมพันธ์ในขณะนี้เป็นตัวกำหนดว่าความสัมพันธ์จะคงอยู่อย่างไร โค้ด Java ของคุณจำเป็นต้องตรวจสอบให้แน่ใจว่ารายการได้รับการอัปเดตอย่างถูกต้อง เนื่องจากตอนนี้ Hibernate จะไม่สนใจด้าน "หนึ่ง" เมื่อทำการล้างเอนทิตี

หากคุณยังต้องการให้ด้าน "หนึ่ง" สามารถเข้าถึงได้ใน Java ให้แมปมันด้วย

@ManyToOne
@JoinColumn(name="...", insertable=false, updatable=false, nullable=false)
person Peter Centgraf    schedule 13.08.2010
comment
เป็นเรื่องตลกที่ตัวอย่างอย่างเป็นทางการสำหรับคอลัมน์ดัชนีที่ชัดเจนใช้ชุดค่าผสม @OneToMany(mappedBy="...") + @OrderColumn ทุกประการ (ดูตัวอย่าง 7.8 ใน docs.jboss.org/hibernate/core/3.6/reference/en-US/html/) - person Chris Lercher; 15.02.2011
comment
หลังจากคำตอบนี้ก็ตกลงกันว่าสถานการณ์จะต้องได้รับการสนับสนุนต่อไป Gail Badner: ฉันยอมรับว่าควรสนับสนุน @OneToMany (mappedBy=...) - person Arjan Tijms; 09.01.2012
comment
มีผู้ให้บริการ JPA อื่น (เช่น Eclipselink) ที่รองรับ @OneToMany (mappedBy="...") หรือไม่ - person deamon; 09.01.2012
comment
การเดาแบบไร้เดียงสาของฉันคือผู้ให้บริการทุกรายสนับสนุนสิ่งนี้ เนื่องจากมันเป็นแผนที่มาตรฐานที่ค่อนข้างดี ตามปกติแล้ว Hibernate เป็นสิ่งที่แปลก โดยพื้นฐานแล้วมันคือ IE6 ภายใต้ผู้ให้บริการ JPA :( - person Mike Braun; 09.01.2012
comment
ตามปกติแล้ว Hibernate จะขัดขวาง: hibernate.onjira.com/browse/HHH-5732 - person Kawu; 18.01.2012
comment
ฉันไม่รู้ว่าทำไมนี่ถึงเป็นรูปแบบความสัมพันธ์ที่แปลก มันไม่ใช่ ลองถามชาว JPA ดูครับ - person Kawu; 04.05.2012
comment
ลิงก์ข้อบกพร่องการไฮเบอร์เนตไม่ถูกต้อง ควรเป็น hibernate.atlassian.net/browse/HHH-5390 . แก้ไขโพสต์ไม่ได้ แนะนำให้แก้ไขคิวเต็ม - person cdalxndr; 22.07.2020
comment
คำตอบนี้ยังคงถูกต้องในปี 2021 หรือไม่ - person Mathew Alden; 01.03.2021

ทำสิ่งนี้:

@Entity
class Parent {

    @OneToMany
    @OrderColumn(name = "pos")
    List<Child> children;
}

@Entity
class Child {

    @ManyToOne
    Parent parent;
    @Column(name = "pos")
    Integer index;

    @PrePersist
    @PreUpdate
    private void prepareIndex() {
        if (parent != null) {
            index = parent.children.indexOf(this);
        }
    }
}
person Daniel De León    schedule 18.09.2012
comment
ฉันคิดว่าใน PreparIndex() ควรเปลี่ยนเป็น index = parent.children.indexOf(this); ถ้า (ดัชนี == -1) ดัชนี = parent.children.size(); - person cn123h; 20.02.2015

คุณควรพยายามระบุ OrderColumn กับเจ้าของการเชื่อมโยง หรือในการแมปของคุณ คุณใส่เจ้าของไว้ที่ลูก เจ้าของควรเป็นผู้ปกครอง (ในการเชื่อมโยงแบบสองทิศทาง เจ้าของคือผู้ที่ไม่มีคีย์เวิร์ด mappedBy ที่นี่คุณใส่คีย์เวิร์ดนี้ในคลาสของผู้ปกครอง จากนั้นคุณ หมายถึงชั้นผู้ปกครองไม่ใช่เจ้าของ)

ในชั้นเรียนลูกของคุณ คุณควรมีคีย์เวิร์ด mappedBy บน parentCollection แต่ไม่ใช่ใน ChildrenCollection
และในคลาสผู้ปกครองของคุณ คุณควรมีคำอธิบายประกอบ @JoinTable บางอย่างเช่นนี้:

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@OrderColumn(name = "pos")
@JoinTable( name = "<NAME_OF_YOUR_TABLE>", joinColumns = @JoinColumn( <JOIN_COLUMNS_...> )
private List<Children> childrenCollection;
person Nico    schedule 08.09.2011