2011-11-02 38 views
9

我的文檔的簡單層次JOINED:休眠4:持續InheritanceType.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) 
); 

正如你可以看到所有的子表做的是從文件共享表相同的ID。除此之外SystemDocuments增加了一個binary_data列,並且​​沒有添加新的屬性。 (還要注意有由'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 
{ 
    ... 
} 

後者類應該被映射到的文檔鑑別器的列值'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); 

在視察DB不過,我可以看到,Hibernate並不插入'external'鑑別器值轉換爲Documents表的discriminator列。

過去一直存在這個問題,請參閱https://hibernate.onjira.com/browse/ANN-140以及最近的Hibernate 4 https://hibernate.onjira.com/browse/HHH-4358,所以很可能會這樣工作。

然後我在當前的Hibernate 4 API Docs中找到了http://docs.jboss.org/hibernate/core/4.0/javadocs/org/hibernate/annotations/DiscriminatorOptions.html,但它不起作用(請參閱Document類的@DiscriminatorOptions)。

如何讓Hibernate 4使用原始註釋插入鑑別器

注意:我不想將鑑別器列映射爲常規列。

回答

19

首先,這個問題是Discriminator in InheritanceType.JOINED的重複。

似乎持續加入繼承中的鑑別值是而不是所需的JPA規範。下面是我從JPA專家組成員通過電子郵件收到什麼:

該規範並不要求實現使用鑑欄來實現JOINED繼承,但是,假設是,如果指定@DiscriminatorColumn那麼它將被使用,即值將被寫出。我們沒有明確說明,如果在代碼中指定@DiscriminatorColumn,它必須被使用,就像我們沒有明確指出,如果@Column或@JoinColumn被指定,那麼值必須存儲在表中,但是隻有我們可以或應該指定的那麼多。在最底層,假定某些物理和理性的規律。

手頭的問題一直是一個問題與Hibernate相當長一段時間,在這裏看到:

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

拒絕評論:

EJB3不需要與使用鑑別的加入映射策略。對於需要鑑別器的JOINED映射策略的較差實現,允許允許。 Hibernate不需要鑑別器,因爲Hibernate比其他劣勢實現更好。

在僅SINGLE_TABLE策略需要辨別字段結束時,JOINED 可以沒有被實現。 Hibernate目前的問題是,當使用@DiscriminatorColumn映射的JOINED繼承中持久化子實體時,即使JPA規範建議在鑑別器與JOINED一起使用時保留鑑別器值,它也會導致數據不一致。查看更多在這裏RFE:

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

+4

有張貼在該票(HHH-6911)日前補充意見。現在看來,Hibernate(4.2.9,4.3.X)在代碼中明確聲明時不再忽略鑑別器列。 – Andy