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,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 { ... }
后一类应被映射到文档的标识符列值“外部”.当通过EntityManager发现实体时,识别符被正确地返回,实际上是因为我的测试数据的识别符被正确插入数据块.
现在我使用以下代码通过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不会将“外部”鉴别器值插入到“文档”表的标识符列中.
过去有一些问题,见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 Class中的@DiscriminatorOptions).
如何让Hibernate 4使用原始注释插入标识符?
注意:我不想将discriminator列映射为常规列.
解决方法
看起来像JOINED继承中的持久性鉴别器值不是JPA规范所要求的.这是我通过电子邮件从JPA专家组的成员收到的内容:
The spec does not require an implementation to use discriminator columns to implement JOINED inheritance,however,the assumption is that if @DiscriminatorColumn is specified then it would be used,i.e. the values would be written out. We do not explicitly state that if a @DiscriminatorColumn is specified in the code it must be used,just like we don’t explicitly state that if a @Column or @JoinColumn is specified the values must be stored in the table,but there is only so much that we can or should specify. At the lowest level,certain laws of physics and reason are just assumed.
手头的问题一直是Hibernate一段时间的问题,请看这里:
https://hibernate.atlassian.net/browse/ANN-140
拒绝评论:
EJB3 does NOT require use of discriminators with JOINED mapping strategies. It is allowed for inferior implementations of the JOINED mapping strategy which require a discriminator. Hibernate does not need a discriminator because Hibernate is better than these other inferior implementations.
最终只有SINGLE_TABLE策略需要一个鉴别器列,JOINED可以实现没有. Hibernate当前的问题是,当使用@DiscriminatorColumn映射的JOINED继承中持久化子实体时,即使JPA规范建议在JOINED中使用鉴别符时,仍然会持久标识符值,因此它将导致不一致的数据.在RFE中查看更多内容: