2011-11-02 18 views
9

Tengo una jerarquía simple unidas de documentos:Hibernate 4: persistente columna discriminadora InheritanceType.JOINED valores

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

Como se puede ver todas las tablas sub hacer es compartir el mismo ID de la tabla de documentos. Aparte de eso, SystemDocuments agrega una columna binary_data y ExternalDocuments no agrega nuevas propiedades. (Tenga en cuenta también que hay otras dos mesas sub concretos en la jerarquía denotado por 'official''individual' y que son de relevancia aquí.)

Estas son las asignaciones para las tablas anteriores:

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

Se supone que la última clase que se asigna a la columna valor discriminador de los documentos 'external'. Al encontrar entidades a través de EntityManager.find, los discriminadores se devuelven correctamente, en realidad porque los discriminadores de mis datos de prueba se han INSERTADO correctamente en la base de datos.

Ahora uso el siguiente código para insertar nuevos documentos/archivos en el sistema a través de la APP y un cargador de archivos:

... 

UploadedFile uf = event.getUploadedFile(); 

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

docService.create(detachedExternalDocument); 

Al inspeccionar el DB sin embargo, puedo ver que Hibernate hace no inserte el 'external' valor del discriminador en la columna de la tabla Documentsdiscriminator.

Ha habido problemas al respecto en el pasado, vea https://hibernate.onjira.com/browse/ANN-140 y más recientemente para Hibernate 4 https://hibernate.onjira.com/browse/HHH-4358, por lo que se supone que funciona de esa manera.

Encontré http://docs.jboss.org/hibernate/core/4.0/javadocs/org/hibernate/annotations/DiscriminatorOptions.html en los documentos API actuales de Hibernate 4, pero no funciona (vea @DiscriminatorOptions en la clase Document).

¿Cómo puedo obtener Hibernate 4 para insertar los discriminadores usando las anotaciones crudas?

Nota: No quiero asignar la columna del discriminador como una columna normal.

Respuesta

19

En primer lugar, esta pregunta es un duplicado de Discriminator in InheritanceType.JOINED.

Parece que los valores discriminadores persistentes en la herencia UNIDAD es no requerido por la especificación JPA.Esto es lo que he recibido de un miembro del grupo de expertos de la APP a través de correo electrónico:

La especificación no requiere una implementación a utilizar columnas discriminador para implementar la herencia Macizo, sin embargo, la suposición es que si no se especifica @DiscriminatorColumn entonces se usaría, es decir, los valores se escribirían. No indicamos explícitamente que si se especifica una @DiscriminatorColumn en el código, debe utilizarse, al igual que no indicamos explícitamente que si se especifica @Column o @JoinColumn, los valores deben almacenarse en la tabla, pero existe solo tanto que podemos o debemos especificar. En el nivel más bajo, se asumen ciertas leyes de la física y la razón.

El problema en cuestión ha sido un problema con Hibernate durante bastante tiempo, ver aquí:

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

comentario de rechazo:

EJB3 no requiere el uso de discriminadores con Estrategias de mapeo UNIDAS Es permitido para implementaciones inferiores de la estrategia de mapeo UNIDO que requieren un discriminador. Hibernate no necesita un discriminador porque Hibernate es mejor que estas otras implementaciones inferiores.

Al final única estrategia SINGLE_TABLE requiere una columna de discriminador, se unió puede implementarse sin. El problema con Hibernate actualmente es que causa datos inconsistentes cuando persisten subentidades en una herencia UNITAR asignada con @DiscriminatorColumn, aunque la especificación JPA recomienda persistir los valores discriminatorios si se utiliza un discriminador con UNID. Ver más en el RFE aquí:

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

+4

Hubo comentarios adicionales publicados en ese boleto (HHH-6911) recientemente. Parece que ahora Hibernate (4.2.9, 4.3.X) ya no ignora la columna del discriminador cuando se establece explícitamente en el código. – Andy

Cuestiones relacionadas