ไม่สามารถใช้การสร้างคีย์คอลัมน์เอกลักษณ์กับ <union-subclass> (TABLE_PER_CLASS)


97

com.something.SuperClass:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class SuperClass implements Serializable {
    private static final long serialVersionUID = -695503064509648117L;

    long confirmationCode;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO) // Causes exception!!!
    public long getConfirmationCode() {
        return confirmationCode;
    }

    public void setConfirmationCode(long confirmationCode) {
        this.confirmationCode = confirmationCode;
    }
}

com.something.SubClass:

@Entity
public abstract class Subclass extends SuperClass {
    private static final long serialVersionUID = 8623159397061057722L;

    String name;

    @Column(nullable = false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

ให้ข้อยกเว้นนี้แก่ฉัน:

Caused by: org.hibernate.MappingException: Cannot use identity column key
generation with <union-subclass> mapping for: com.something.SuperClass

วิธีใดดีที่สุดและสะดวกที่สุดสำหรับฉันในการสร้าง ID ฉันไม่ต้องการเปลี่ยนกลยุทธ์การสืบทอด

คำตอบ:


233

นี่คือปัญหาที่คุณผสม "ตารางต่อคลาส" GenerationType.Autoมรดกและ พิจารณาคอลัมน์ประจำตัวใน MsSQL เป็นคอลัมน์ ในกลยุทธ์ "ตารางต่อคลาส" คุณใช้หนึ่งตารางต่อชั้นเรียนและแต่ละตารางจะมีรหัส

ลอง:

@GeneratedValue(strategy = GenerationType.TABLE)


2
โซลูชั่นที่สมบูรณ์แบบ แม้แต่ฟอรัม Hibernate ก็ดูเหมือนจะไม่มีวิธีแก้ปัญหานี้และพวกเขากำลังไปรอบ ๆ หัวข้อforum.hibernate.org/…
Spring Monkey

1
ปัญหานี้เกิดขึ้นกับ MySql เท่านั้นหรือเป็นเรื่องปกติเมื่อฉันดูวิดีโอหนึ่งสำหรับวิธีการแบบตารางต่อชั้นเรียนและใช้งานได้ดีใน postgres นั้นถูกใช้
Prashant

1
ฉันพบสิ่งนี้เมื่อเร็ว ๆ นี้เมื่อทดสอบแอปพลิเคชัน Dropwizard ในกรณีของฉันฉันแก้ไขโดยตรวจสอบให้แน่ใจว่าได้ใช้ตัวเลือกการกำหนดค่าเดียวกับที่ DW ใช้เพื่อสร้างโรงงานเซสชัน ฉันค่อนข้างแน่ใจว่าการตั้งค่าคุณสมบัติ "hibernate.id.new_generator_mappings" เป็น true คือสิ่งที่แก้ไขได้ นี่คือ DW 0.7.0, Hibernate 4.3.1, DB คือ H2
sfitts

1
มันทำงานได้อย่างสมบูรณ์ อย่างไรก็ตามขอแนะนำอย่างยิ่งว่าไม่ควรใช้กลยุทธ์การสร้างรหัส 'TABLE' เนื่องจากจะเรียกใช้การสืบค้นจำนวนมาก (เลือกแทรกและอัปเดต) และรักษาการล็อกเพื่อสร้างค่าที่ไม่ซ้ำกันสำหรับคีย์หลัก แล้วอะไรจะเป็นทางเลือกอื่นในการแก้ปัญหานี้หากเรามีสถานการณ์มรดกที่ยิ่งใหญ่ แน่นอนมันจะส่งผลต่อประสิทธิภาพในระดับที่ดี
MAC

8

ฉันสงสัยว่านี่เป็นปัญหาเฉพาะของฐานข้อมูลหรือไม่เนื่องจากดูบทช่วยสอนของ YouTube ด้วย PostgreSQL เป็นฐานข้อมูลที่สำคัญฉันเห็นว่าผู้สร้างวิดีโอเรียกใช้แอปที่มีค่าเริ่มต้น @GeneratedValue ได้สำเร็จ ในกรณีของฉัน (ฐานข้อมูลพื้นฐานคือ MySQL) ฉันต้องแก้ไขกลยุทธ์ @GeneratedValue เป็น GenerationType.TABLE ตรงตามที่ zoidbeck เสนอ

นี่คือวิดีโอ: https://www.youtube.com/watch?v=qIdM4KQOtH8


Postgres สามารถทำการสืบทอดได้ดังนั้นคุณอาจคิดถูกว่านี่เป็นฐานข้อมูลเฉพาะ: postgresql.org/docs/8.1/static/ddl-inherit.htmlวิดีโอไม่ได้อธิบาย (หรือฉันพลาดไป) ว่าสคีมาถูกสร้างขึ้นอย่างไร ดังนั้นภาษาถิ่นของ NHibernate postgres อาจทำได้ด้วยตัวเองหรือคุณต้องเพิ่ม 'INHERITS' ด้วยตนเองแทน ที่จริงฉันไม่สามารถบอกได้
zoidbeck

6
เกี่ยวกับ PostgreSQL, Hibernate GenerationType.SEQUENCEค่าเริ่มต้นใช้งาน นั่นเป็นเหตุผลที่มันทำงานโดยอัตโนมัติที่นั่น มันมีอย่างไม่มีอะไรจะทำอย่างไรกับ INHERITSPostgreSQLs
Henning

ฉันใช้แบบฝึกหัดเดียวกันและการใช้ @Generated ทำให้เกิดปัญหาเมื่อฉันใช้ MySql ใช้เวลาในการดีบักนานมากจนกระทั่งฉันเห็นโพสต์นี้
Deen John

5

เห็นด้วยกับคำตอบของ zoidbeck คุณต้องเปลี่ยนกลยุทธ์เป็น:

@GeneratedValue(strategy = GenerationType.TABLE)

แต่นั่นไม่ใช่ทั้งหมดคุณต้องสร้างตารางใหม่สิ่งที่จะยึดลำดับคีย์หลักของตารางบทคัดย่อของคุณ แก้ไขการแมปของคุณเป็น

@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ConfirmationCodeGenerator")
@TableGenerator(table = "SEQUENCES", name = "ConfirmationCodeGenerator")
public long getConfirmationCode() {
   return confirmationCode;
}

และตารางใหม่ในฐานข้อมูลควรมีลักษณะดังนี้: ป้อนคำอธิบายภาพที่นี่

เมื่อคุณรันแอปพลิเคชันของคุณไฮเบอร์เนตจะแทรกแถวที่sequence_nameจะเป็นชื่อเอนทิตี ( SuperClassในตัวอย่างนี้) และsequence_next_hi_valueค่าจะเพิ่มขึ้นโดยอัตโนมัติและใช้สำหรับบันทึกใหม่ของตารางคลาสย่อยที่ใช้งานทั้งหมด


2

ในกรณีของเราเราใช้ฐานข้อมูล PostreSQL สำหรับ dev และ production และฐานข้อมูล hsqldb ในหน่วยความจำสำหรับการทดสอบ เรากำลังใช้ลำดับในทั้งสองกรณีเพื่อสร้างรหัส เห็นได้ชัดว่าเป็นGenerationType.AUTOค่าเริ่มต้นSEQUENCEสำหรับ postgres แต่ล้มเหลวในการทดสอบในพื้นที่ของเรา (ต้องตั้งค่าเริ่มต้นเป็นอย่างอื่นสำหรับ hsqldb)

GenerationType.SEQUENCEดังนั้นวิธีการแก้ปัญหาที่ทำงานให้เราใช้งานอย่างชัดเจน



0

มีการปฏิบัติตามมาตรฐาน SQL ระหว่าง MySQL และ PostgreSQL PostgreSQL Postgres เข้าใจชุดย่อยที่ดีของ SQL92 / 99 รวมทั้งคุณลักษณะเชิงวัตถุบางอย่างสำหรับชุดย่อยเหล่านี้ Postgres สามารถจัดการกับกิจวัตรและกฎที่ซับซ้อนได้เช่นเคียวรี SQL ที่เปิดเผย, เคียวรีย่อย, มุมมอง, การสนับสนุนผู้ใช้หลายคน, ธุรกรรม, การเพิ่มประสิทธิภาพคิวรี, การสืบทอดและอาร์เรย์ ไม่สนับสนุนการเลือกข้อมูลจากฐานข้อมูลต่างๆ

MySQL MySQL ใช้ SQL92 เป็นรากฐาน ทำงานบนแพลตฟอร์มจำนวนนับไม่ถ้วน Mysql สามารถสร้างแบบสอบถามที่สามารถเข้าร่วมตารางจากฐานข้อมูลที่แตกต่างกัน รองรับการรวมภายนอกทั้งซ้ายและขวาโดยใช้ทั้งไวยากรณ์ ANSI และ ODBC ตั้งแต่ MySQL 4.1 นับจากรีลีสนั้น MySQL จะจัดการเคียวรีย่อย มุมมองที่รองรับเมื่อรุ่น 5

สำหรับคำอธิบายโดยละเอียดโปรดไปที่ http://www-css.fnal.gov/dsg/external/freeware/pgsql-vs-mysql.html


โปรดอย่ารู้สึกแย่กับเรื่องนี้ แต่ฉันคิดว่าการเปรียบเทียบ MySQL และ PostgreSQL นั้นไม่เกี่ยวข้องกับหัวข้อนี้ (แม้ว่าค่าเริ่มต้นของไฮเบอร์เนตจะแตกต่างกันสำหรับพวกเขาก็ตาม)
mrts
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.