2011-11-02 12 views
9

Ho una semplice struttura congiunta di documenti:Hibernate 4: persistente colonna discriminatore InheritanceType.JOINED valori

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) 
); 

Come si può vedere tutti i tavoli sotto fare è di condividere lo stesso ID dalla tabella Documenti. Oltre a ciò, SystemDocuments aggiunge una colonna binary_data e ExternalDocuments non aggiunge nuove proprietà. (Si noti inoltre ci sono altri due tavoli sub concreti nella gerarchia indicata con 'official' e 'individual' che sono di nessuna rilevanza qui.)

Ecco le mappature per le tabelle di cui sopra:

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 
{ 
    ... 
} 

si suppone Quest'ultima classe per essere mappato discriminatore valore della colonna dei Documenti 'external'. Quando si cercano entità tramite EntityManager.find i discriminatori vengono restituiti correttamente, in realtà perché i discriminatori dei miei dati di test sono stati INSERITI correttamente nel DB.

ora uso il seguente codice per inserire nuovi documenti/file nel sistema tramite APP e un file uploader:

... 

UploadedFile uf = event.getUploadedFile(); 

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

docService.create(detachedExternalDocument); 

Quando si controlla la DB tuttavia posso vedere che Hibernate fa non inserire la 'external' discriminatore nella colonna discriminator della tabella della tabella.

Non ci sono stati problemi su questo in passato, vedi https://hibernate.onjira.com/browse/ANN-140 e più recentemente per Hibernate 4 https://hibernate.onjira.com/browse/HHH-4358, quindi è probabile che si suppone di lavorare in questo modo.

Ho quindi trovato http://docs.jboss.org/hibernate/core/4.0/javadocs/org/hibernate/annotations/DiscriminatorOptions.html nell'attuale Documento API di Hibernate 4, ma non funziona (vedere @DiscriminatorOptions nella classe Documento).

Come è possibile attivare Hibernate 4 per inserire i discriminatori utilizzando le annotazioni non elaborate?

Nota: Non voglio mappare la colonna discriminatore come una colonna regolare.

risposta

19

Prima di tutto, questa domanda è un duplicato di Discriminator in InheritanceType.JOINED.

Sembra che la persistenza dei valori di discriminatore nell'eredità JOINED sia non richiesta dalle specifiche JPA.Ecco quello che ho ricevuto da un membro del gruppo di esperti APP via e-mail:

Le specifiche non richiede un'implementazione di utilizzare colonne discriminatore per implementare l'ereditarietà RIUNITE, tuttavia, l'ipotesi è che se @DiscriminatorColumn è specificato allora sarebbe usato, cioè i valori verrebbero scritti. Non dichiariamo esplicitamente che se un codice @DiscriminatorColumn è specificato nel codice deve essere usato, proprio come non si specifica esplicitamente che se si specifica @Column o @JoinColumn i valori devono essere memorizzati nella tabella, ma c'è solo così tanto che possiamo o dovremmo specificare. Al livello più basso, si presumono certe leggi della fisica e della ragione.

Il problema in questione è stato un problema con Hibernate per un bel po ', vedere qui:

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

Rifiuto commento:

EJB3 non richiede l'utilizzo di discriminatori con JOINED strategie di mappatura. E 'ammessi per le implementazioni inferiori della strategia di mappatura RIUNITE che richiedono un discriminatore. Hibernate non ha bisogno di un discriminatore perché Hibernate è migliore di queste altre implementazioni inferiori.

Alla fine solo strategia SINGLE_TABLE richiede una colonna discriminatore, uniti possono essere eseguiti senza. Il problema con Hibernate al momento è che causa dati incoerenti quando si conservano entità secondarie in un'eredità JOINED mappata con @DiscriminatorColumn, anche se la specifica JPA consiglia di mantenere i valori discriminatori se si utilizza un discriminatore con JOINED. Scopri di più su del RFE qui:

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

+4

C'erano ulteriori commenti pubblicati su quel biglietto (HHH-6911) di recente. Sembra ora Hibernate (4.2.9, 4.3.X) non ignora la colonna discriminatore quando viene esplicitamente affermato nel codice. – Andy

Problemi correlati