2011-11-02 11 views
9

Mam proste dołączył hierarchię dokumentów:Hibernate 4: utrzymująca InheritanceType.JOINED kolumnę dyskryminatora wartości

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

Jak widać wszystkie tabele podrzędne zrobić, to podzielić ten sam identyfikator z tabeli dokumenty. Poza tym SystemDocuments dodaje kolumnę binary_data, a ExternalDocuments nie dodaje żadnych nowych właściwości. (Należy również pamiętać, istnieją dwa inne konkretne tabele podrzędne w hierarchii oznaczonej 'official' i 'individual' które są tu bez znaczenia.)

Oto mapowania dla powyższych tabelach:

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

Ta ostatnia klasa ma być mapowany do dyskryminatora wartości kolumnie Dokumenty 'external'. Podczas wyszukiwania jednostek za pośrednictwem EntityManager.find, zwracane są poprawnie, właściwie dlatego, że dyskryminatory moich danych testowych zostały poprawnie wstawione do DB.

Teraz używam następujący kod do wstawienia nowych dokumentów/plików do systemu poprzez WZP i uploader pliku:

... 

UploadedFile uf = event.getUploadedFile(); 

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

docService.create(detachedExternalDocument); 

Podczas sprawdzania DB jednak widzę, że Hibernate robi nie włóż 'external' wartości dyskryminatora w kolumnie Documents tabeli discriminator.

W przeszłości pojawiały się problemy z tym związane, patrz https://hibernate.onjira.com/browse/ANN-140, a ostatnio dla Hibernate 4 https://hibernate.onjira.com/browse/HHH-4358, więc istnieje prawdopodobieństwo, że będzie działać w ten sposób.

Następnie znalazłem http://docs.jboss.org/hibernate/core/4.0/javadocs/org/hibernate/annotations/DiscriminatorOptions.html w bieżących dokumentach API Hibernuj 4, ale to nie działa (zobacz @DiscriminatorOptions w klasie Dokument).

W jaki sposób mogę uzyskać oprogramowanie Hibernate 4 do wstawiania dyskryminatorów za pomocą nieprzetworzonych adnotacji?

Uwaga: Nie chcę odwzorowywać kolumny dyskryminującej jako zwykłej kolumny.

Odpowiedz

19

Po pierwsze, to pytanie jest duplikatem Discriminator in InheritanceType.JOINED.

Wygląda na to, że utrzymujące się wartości dyskryminatora w połączeniu JOINED to , a nie wymagane przez specyfikację JPA.Oto, co otrzymaliśmy od członka grupy ekspertów JPA poprzez e-mail:

Spec nie wymaga implementacji w użyciu kolumny dyskryminacyjne wdrożenie dołączył do dziedziczenia, jednak założenie, że jeśli @DiscriminatorColumn podano wtedy byłby używany, tzn. wartości byłyby wypisane. Nie stwierdzamy jednoznacznie, że jeśli @DiscriminatorColumn jest podana w kodzie, musi być użyta, tak jak nie stwierdzamy wprost, że jeśli podana jest kolumna @Column lub @JoinColumn, wartości muszą być zapisane w tabeli, ale istnieje tylko tyle, że możemy lub powinniśmy określić. Na najniższym poziomie właśnie zakłada się pewne prawa fizyki i rozumu.

Problem pod ręką nie było problemu z Hibernate na dłuższą chwilę, zobacz tutaj:

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

komentarz Odrzucenie:

EJB3 nie wymaga użycia dyskryminatorów z ŁĄCZONE strategie mapowania. Jest dozwolone dla gorszej implementacji strategii odwzorowania połączenia, która wymaga dyskryminatora. Hibernate nie potrzebuje dyskryminatora, ponieważ Hibernate jest lepszy niż te inne słabsze implementacje.

W końcu tylko SINGLE_TABLE strategia wymaga kolumnę dyskryminacyjne, POŁĄCZONE mogą być realizowane bez. Problem z Hibernacją polega obecnie na tym, że powoduje on niespójne dane w przypadku utrzymywania obiektów podrzędnych w powiązaniu JOINED odwzorowanym przy użyciu @DiscriminatorColumn, mimo że specyfikacja JPA zaleca utrzymywanie wartości dyskryminatora, jeśli dyskryminator jest używany z połączeniem JOINED. Zobacz więcej w RFE tutaj:

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

+4

Były dodatkowe komentarze zamieszczone na tym bilecie (HHH-6911) ostatnio. Wygląda na to, że Hibernate (4.2.9, 4.3.X) nie ignoruje już kolumny dyskryminacyjnej, gdy jest ona wyraźnie podana w kodzie. – Andy

Powiązane problemy