Không thể sử dụng tạo khóa cột nhận dạng với <union-subclass> (TABLE_PER_CLASS)


95

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

Cho tôi ngoại lệ này:

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

Cách tốt nhất và thuận tiện nhất để tôi tạo ID là gì? Tôi không muốn thay đổi chiến lược thừa kế của mình.

Câu trả lời:


229

Vấn đề ở đây là bạn kết hợp thừa kế "table-per-class" và GenerationType.Auto. Hãy xem xét một cột nhận dạng trong MsSQL. Nó dựa trên cột. Trong chiến lược "bảng cho mỗi lớp", bạn sử dụng một bảng cho mỗi lớp và mỗi bảng có một ID.

Thử:

@GeneratedValue(strategy = GenerationType.TABLE)


2
Giải pháp hoàn hảo. Ngay cả các diễn đàn Hibernate dường như không có giải pháp này, và họ đã đi quanh chủ đề forum.hibernate.org/…
Spring Monkey

1
Là vấn đề này là với MySql chỉ hoặc thường xuyên của nó như tôi xem một trong một đoạn video cho Bảng mỗi cách tiếp cận lớp học và nó đã được tốt trong postgres rằng làm việc đã được sử dụng
Prashant

1
Tôi đã gặp phải vấn đề này gần đây khi thử nghiệm một ứng dụng Dropwizard. Trong trường hợp của tôi, tôi đã giải quyết bằng cách đảm bảo sử dụng cùng các tùy chọn cấu hình được DW sử dụng để tạo nhà máy phiên. Tôi khá chắc chắn rằng việc đặt thuộc tính "hibernate.id.new_generator_mappings" thành true là điều đã khắc phục sự cố. Đây là DW 0.7.0, Hibernate 4.3.1, DB là H2.
sfitts

1
Nó hoạt động hoàn hảo. Tuy nhiên, chúng tôi khuyên bạn không nên sử dụng chiến lược tạo id 'TABLE' vì nó kích hoạt rất nhiều truy vấn (chọn, chèn và cập nhật) và duy trì khóa để tạo giá trị duy nhất cho khóa chính. Vì vậy, giải pháp thay thế sẽ là gì nếu chúng ta có một tình huống Thừa kế lớn? Nó chắc chắn sẽ ảnh hưởng đến hiệu suất ở mức độ lớn.
MAC

8

Tôi tự hỏi liệu đây có phải là một vấn đề cụ thể của phương ngữ cơ sở dữ liệu hay không, vì xem một hướng dẫn trên youtube với PostgreSQL làm cơ sở dữ liệu cơ bản, tôi thấy rằng người tạo video đã chạy thành công một ứng dụng với @GeneratedValue mặc định. Trong trường hợp của tôi (cơ sở dữ liệu cơ bản là MySQL), tôi đã phải sửa đổi chiến lược @GeneratedValue thành GenerationType.TABLE chính xác như zoidbeck đề xuất.

Đây là video: https://www.youtube.com/watch?v=qIdM4KQOtH8


Postgres có thể thực hiện kế thừa, vì vậy bạn có thể đúng rằng đây là cơ sở dữ liệu cụ thể: postgresql.org/docs/8.1/static/ddl-inherit.html Video không giải thích (hoặc tôi đã bỏ qua) cách lược đồ được tạo. Vì vậy, có thể phương ngữ NHibernate postgres có thể tự làm điều đó hoặc thay vào đó bạn phải thêm 'INHERITS' theo cách thủ công. Trên thực tế, tôi không thể nói.
zoidbeck

6
Trên PostgreSQL, mặc định sử dụng Hibernate GenerationType.SEQUENCE. Đó là lý do tại sao nó hoạt động tự động ở đó. Nó hoàn toàn không liên quan gì đến PostgreSQL INHERITS.
Henning

Tôi đã sử dụng cùng một hướng dẫn và việc sử dụng @Generated đã gây ra sự cố vì tôi đang sử dụng MySql. Đã dành rất nhiều thời gian để gỡ lỗi cho đến khi tôi thấy bài đăng này
Deen John

5

Đồng ý với câu trả lời của zoidbeck. Bạn cần thay đổi chiến lược thành:

@GeneratedValue(strategy = GenerationType.TABLE)

Nhưng đó không phải là tất cả, bạn cần tạo một bảng mới, thứ sẽ chứa chuỗi khóa chính của bảng tóm tắt của bạn. Sửa đổi ánh xạ của bạn thành

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

Và một bảng mới trong cơ sở dữ liệu sẽ trông giống như sau: nhập mô tả hình ảnh ở đây

Khi bạn chạy ứng dụng của mình, Hibernate sẽ chèn một hàng nơi sequence_namesẽ là tên thực thể ( SuperClasstrong ví dụ này) và sequence_next_hi_valuegiá trị sẽ tự động tăng lên và được sử dụng cho các bản ghi mới của tất cả các bảng của lớp con đang triển khai.


2

Trong trường hợp của chúng tôi, chúng tôi sử dụng cơ sở dữ liệu PostreSQL cho nhà phát triển và sản xuất và cơ sở dữ liệu hsqldb trong bộ nhớ để kiểm tra. Chúng tôi đang sử dụng một chuỗi trong cả hai trường hợp để tạo một id. Rõ ràng là GenerationType.AUTOmặc định SEQUENCEcho postgres, nhưng không thành công trong các thử nghiệm cục bộ của chúng tôi (phải mặc định thành thứ khác cho hsqldb).

Vì vậy, giải pháp đã làm việc cho chúng tôi, hãy sử dụng một cách rõ ràng GenerationType.SEQUENCE.


1

bạn có thể sử dụng @MappedSuperclass để kế thừa


0

Có một Tuân thủ tiêu chuẩn SQL giữa MySQL và PostgreSQL. PostgreSQL Postgres hiểu một tập hợp con tốt của SQL92 / 99 cộng với một số tính năng hướng đối tượng cho các tập con này. Postgres có khả năng xử lý các quy trình và quy tắc phức tạp như truy vấn SQL khai báo, truy vấn con, chế độ xem, hỗ trợ nhiều người dùng, giao dịch, tối ưu hóa truy vấn, kế thừa và mảng. Không hỗ trợ chọn dữ liệu trên các cơ sở dữ liệu khác nhau.

MySQL MySQL sử dụng SQL92 làm nền tảng. Chạy trên vô số nền tảng. Mysql có thể xây dựng các truy vấn có thể nối các bảng từ các cơ sở dữ liệu khác nhau. Hỗ trợ cả phép nối bên ngoài trái và phải bằng cách sử dụng cả cú pháp ANSI và ODBC. Kể từ phiên bản MySQL 4.1 trở đi, MySQL sẽ xử lý các truy vấn con. Chế độ xem được hỗ trợ kể từ bản phát hành 5.

Để có một mô tả chi tiết, vui lòng truy cập. http://www-css.fnal.gov/dsg/external/freeware/pgsql-vs-mysql.html


Xin đừng cảm thấy tệ về điều này, nhưng tôi nghĩ rằng so sánh MySQL và PostgreSQL không liên quan đến chủ đề (mặc dù mặc dù mặc định Hibernate khác nhau đối với chúng).
mrts
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.