Hibernate 4:持久化InheritanceType.JOINED鉴别器列值

Kaw*_*awu 10 java inheritance hibernate jpa discriminator

我有一个简单的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)
);
Run Code Online (Sandbox Code Playgroud)

如您所见,所有子表都与Documents表共享相同的ID.除此之外,SystemDocuments添加一binary_data列并且不ExternalDocuments添加任何新属性.(还要注意有层次结构中表示为其他两个具体子表'official''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;

    ...
}
Run Code Online (Sandbox Code Playgroud)

SystemDocument.java:

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

ExternalDocument.java:

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

后一类应该映射到Documents的鉴别器列值'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);
Run Code Online (Sandbox Code Playgroud)

但是在检查DB时,我可以看到Hibernate 没有'external'鉴别器值插入Documents表的discriminator列中.

过去有过这方面的问题,请参阅https://hibernate.onjira.com/browse/ANN-140以及最近的Hibernate 4 https://hibernate.onjira.com/browse/HHH-4358,所以很有可能它应该以这种方式工作吗?

然后我在当前的Hibernate 4 API文档中找到了http://docs.jboss.org/hibernate/core/4.0/javadocs/org/hibernate/annotations/DiscriminatorOptions.html,但它不起作用(参见@DiscriminatorOptions)文件类).

如何让Hibernate 4 使用原始注释插入鉴别

注意:我不想将鉴别器列映射为常规列.

Kaw*_*awu 20

首先,这个问题与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

  • 最近在该机票(HHH-6911)上发布了其他评论.现在看来,Hibernate(4.2.9,4.3.X)在代码中明确说明时不再忽略鉴别器列. (4认同)