10

ドキュメントの単純なJOINED階層があります。

CREATE TABLE Documents
(
  id INTEGER NOT NULL,
  discriminator ENUM('official','individual','external') NOT NULL,
  file_name VARCHAR(200) NOT NULL,
  PRIMARY KEY (id)
);

CREATE SystemDocuments
(
  id INTEGER NOT NULL,
  binary_data BLOB NOT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (id) REFERENCES Documents (id)
);

CREATE ExternalDocuments
(
  id INTEGER NOT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (id) REFERENCES SystemDocuments (id)
);

ご覧のとおり、すべてのサブテーブルはDocumentsテーブルの同じIDを共有しています。それ以外SystemDocumentsは、binary_data列をExternalDocuments追加し、新しいプロパティを追加しません。'official'(また、で示される階層には他に2つの具体的なサブテーブルが'individual'あり、ここでは関連性がないことに注意してください。)

上記のテーブルのマッピングは次のとおりです。

Document.java

@Entity
@Table(name = "Documents")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
//@DiscriminatorOptions(force = true) // <-- Hibernate 4-specific annotation not inserting discriminator values
public abstract class Document implements Serializable
{
    @Id
    @Column
    protected Integer id;

    @Column(name = "file_name")
    protected String fileName;

    ...
}

SystemDocument.java

@Entity
@Table(name = "SystemDocuments")
public abstract class SystemDocument extends Document
{
    @Lob
    @Column(name = "binary_data")
    protected byte[] binaryData;

    ...
}

ExternalDocument.java

@Entity
@Table(name = "ExternalDocuments")
@DiscriminatorValue(value = "external")
public class ExternalDocument extends SystemDocument
{
    ...
}

後者のクラスは、ドキュメントのディスクリミネーター列の値にマップされることになっています'external'。EntityManager.findを介してエンティティを検索すると、ディスクリミネーターが正しく返されます。これは、実際には、テストデータのディスクリミネーターがDBに正しく挿入されているためです。

次に、次のコードを使用して、JPAとファイルアップローダーを介して新しいドキュメント/ファイルをシステムに挿入します。

...

UploadedFile uf = event.getUploadedFile();

// set ID, file name, and binary data
ExternalDocument detachedExternalDocument =
    new ExternalDocument(1234567, uf.getName(), uf.getData());

docService.create(detachedExternalDocument);

ただし、DBを調べると、Hibernateがディスクリミネーター値をテーブルの列に挿入していないことがわかります。'external'Documentsdiscriminator

これについては過去に問題がありました。https://hibernate.onjira.com/browse/ANN-140を参照してください。最近では、Hibernate 4https : //hibernate.onjira.com/browse/HHH-4358を参照してください。それはそのように機能することになっていますか?

次に、現在のHibernate 4 APIドキュメントでhttp://docs.jboss.org/hibernate/core/4.0/javadocs/org/hibernate/annotations/DiscriminatorOptions.htmlを見つけましたが、機能しません(@DiscriminatorOptionsを参照してください。ドキュメントクラス)。

生の注釈を使用してHibernate4に識別子を挿入するにはどうすればよいですか?

:ディスクリミネーター列を通常の列としてマップしたくありません。

4

1 に答える 1

22

まず、この質問はInheritanceType.JOINED の Discriminatorの複製です。

JPA仕様では、JOINED継承で識別子の値を永続化する必要はないようです。JPAエキスパートグループのメンバーから電子メールで受け取ったものは次のとおりです。

仕様では、JOINED 継承を実装するために識別子列を使用する実装は必要ありませんが、 @DiscriminatorColumn が指定されている場合は、それが使用される、つまり値が書き出されることが想定されています。@DiscriminatorColumn がコードで指定されている場合、それを使用する必要があることを明示的に述べていません。これは、@Column または @JoinColumn が指定されている場合、値をテーブルに格納する必要があることを明示的に述べていないのと同じですが、指定できる、または指定する必要があるだけです。最低レベルでは、特定の物理法則と理性が想定されています。

当面の問題は、かなり長い間 Hibernate の問題でした。こちらを参照してください。

https://hibernate.atlassian.net/browse/ANN-140

却下コメント:

EJB3 では、JOINED マッピング戦略で識別子を使用する必要はありません。これは、ディスクリミネータを必要とする JOINED マッピング戦略の劣った実装では許容されます。Hibernate はこれらの他の劣った実装よりも優れているため、Hibernate はディスクリミネーターを必要としません。

最後に、SINGLE_TABLE 戦略のみが識別子列を必要とし、JOINEDはなくても実装できます現在の Hibernate の問題は、@DiscriminatorColumn でマップされた JOINED 継承でサブエンティティを永続化すると、データの一貫性が失われることです。ただし、JPA 仕様では、識別子が JOINED で使用されている場合は識別子の値を永続化することが推奨されています。詳細については、こちらの RFE を参照してください。

https://hibernate.atlassian.net/browse/HHH-6911

于 2011-12-20T13:42:56.000 に答える