web-dev-qa-db-ja.com

<union-subclass>(TABLE_PER_CLASS)でID列キー生成を使用できません

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を生成するための最良かつ最も便利な方法は何ですか? 継承戦略を変更したくありません。

86
user14070

ここでの問題は、「クラスごとのテーブル」継承と_GenerationType.Auto_を混在させることです。 MsSQLのID列を検討してください。列ベースです。 「クラスごとのテーブル」戦略では、クラスごとに1つのテーブルを使用し、各テーブルにはIDがあります。

試してください:

@GeneratedValue(strategy = GenerationType.TABLE)

208
zoidbeck

これはデータベース方言特有の問題なのだろうか、PostgreSQLを基礎データベースとするyoutubeチュートリアルを見て、ビデオの作成者がデフォルトの@GeneratedValueでアプリを正常に実行しているのを見たので。私の場合(基礎となるデータベースはMySQLです)、@ GeneratedValueストラテジーをzoidbeckが提案するとおりにGenerationType.TABLEに修正する必要がありました。

ビデオはこちら: https://www.youtube.com/watch?v=qIdM4KQOtH8

8
skiabox

ゾイドベックの答えに同意します。戦略を次のように変更する必要があります。

@GeneratedValue(strategy = GenerationType.TABLE)

しかし、それだけではありません。新しいテーブルを作成する必要があります。これは、アブストラクトのテーブルの主キーシーケンスを保持するものです。マッピングを変更します

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

データベース内の新しいテーブルは次のようになります。 enter image description here

アプリケーションを実行すると、Hibernateはsequence_nameはエンティティ名(この例ではSuperClass)とsequence_next_hi_value値は自動的にインクリメントされ、すべての実装サブクラスのテーブルの新しいレコードに使用されます。

2
Gondy

このケースでは、開発と本番にはPostreSQLデータベースを使用し、テストにはインメモリhsqldbデータベースを使用します。 IDを生成するために両方のケースでシーケンスを使用しています。どうやらGenerationType.AUTOは、postgresではデフォルトでSEQUENCEになりますが、ローカルテストでは失敗しました(hsqldbではデフォルトで他の何かにする必要があります)。

そこで私たちのために働いた解決策は、明示的にGenerationType.SEQUENCE

2
Ryan Walls

継承に@MappedSuperclassを使用できます

1
leimbag

MySQLとPostgreSQLの間にSQL標準準拠があります。PostgreSQL Postgresは、SQL92/99の優れたサブセットと、これらのサブセットに対するいくつかのオブジェクト指向機能を理解しています。 Postgresは、宣言的なSQLクエリ、サブクエリ、ビュー、マルチユーザーサポート、トランザクション、クエリ最適化、継承、および配列として、複雑なルーチンとルールを処理できます。異なるデータベース間でのデータの選択はサポートしていません。

MySQL MySQLはその基礎としてSQL92を使用します。無数のプラットフォームで実行されます。 Mysqlは、異なるデータベースのテーブルを結合できるクエリを構築できます。 ANSIとODBC構文の両方を使用して、左右の外部結合をサポートします。そのリリース以降のMySQL 4.1の時点で、MySQLはサブクエリを処理します。

詳細な説明については、をご覧ください。 http://www-css.fnal.gov/dsg/external/freeware/pgsql-vs-mysql.html

0
Coderac