我有一个简单的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'
和'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
{
...
}
后一类应该映射到Documents的鉴别器列值'external'
。通过EntityManager.find查找实体时,正确地返回了鉴别器,实际上是因为我的测试数据的鉴别器已经正确地插入到数据库中。
现在我使用以下代码通过JPA和文件上传器将新文档/文件插入系统:
...
UploadedFile uf = event.getUploadedFile();
// set ID, file name, and binary data
ExternalDocument detachedExternalDocument =
new ExternalDocument(1234567, uf.getName(), uf.getData());
docService.create(detachedExternalDocument);
在检查数据库时,我可以看到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,但它不起作用(请参阅Document类中的@DiscriminatorOptions)。
如何让Hibernate 4使用原始注释插入鉴别器?
注意:我不想将鉴别器列映射为常规列。
答案 0 :(得分:20)
首先,这个问题与Discriminator in InheritanceType.JOINED重复。
似乎JOAED继承中的持久化鉴别器值是JPA规范要求的不。以下是我通过电子邮件从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中的更多信息: