usadas tablas provienen para paquete mapear las joined herencia con anotaciones hibernate inheritance jpa annotations hierarchy

tablas - las anotaciones usadas para mapear con hibernate provienen del paquete



¿Cómo mezclar estrategias de herencia con anotaciones JPA e Hibernate? (2)

De acuerdo con la documentación de referencia de Hibernate, debería ser posible mezclar diferentes estrategias de mapeo de herencia al usar los metadatos XML de Hibernate (...)

En realidad, no es realmente compatible, están "engañando" usando una tabla secundaria para cambiar de la estrategia de tabla única en el ejemplo de la documentación. Citando la persistencia de Java con Hibernate :

Puede mapear jerarquías de herencia completas anidando elementos de mapeo <union-subclass> , <sub- class> , y <joined-subclass> . No puede mezclarlos, por ejemplo, para pasar de una jerarquía de tabla por clase con un discriminador a una estrategia normalizada de tabla por subclase. Una vez que haya tomado una decisión sobre una estrategia de herencia, debe apegarse a ella .

Esto no es completamente cierto, sin embargo. Con algunos trucos de Hibernate, puede cambiar la estrategia de asignación para una subclase particular. Por ejemplo, puede asignar una jerarquía de clases a una sola tabla, pero para una determinada subclase, cambie a una tabla separada con una estrategia de asignación de claves externas , al igual que con la tabla por subclase. Esto es posible con el elemento de correlación <join> :

<hibernate-mapping> <class name="BillingDetails" table="BILLING_DETAILS"> <id>...</id> <discriminator column="BILLING_DETAILS_TYPE" type="string"/> ... <subclass name="CreditCard" discriminator-value="CC"> <join table="CREDIT_CARD"> <key column="CREDIT_CARD_ID"/> <property name="number" column="CC_NUMBER"/> <property name="expMonth" column="CC_EXP_MONTH"/> <property name="expYear" column="CC_EXP_YEAR"/> ... </join> </subclass> <subclass name="BankAccount" discriminator-value="BA"> <property name=account" column="BA_ACCOUNT"/> ... </subclass> ... </class> </hibernate-mapping>

Y podrías lograr lo mismo con las anotaciones:

Java Persistence también admite esta estrategia de mapeo de herencia mixta con anotaciones. Asigne la superclase BillingDetails con InheritanceType.SINGLE_TABLE , tal como lo hizo anteriormente. Ahora asigne la subclase que desea separar de la tabla única a una tabla secundaria.

@Entity @DiscriminatorValue("CC") @SecondaryTable( name = "CREDIT_CARD", pkJoinColumns = @PrimaryKeyJoinColumn(name = "CREDIT_CARD_ID") ) public class CreditCard extends BillingDetails { @Column(table = "CREDIT_CARD", name = "CC_NUMBER", nullable = false) private String number; ... }

No probé esto, pero tal vez podrías intentar:

  • mapa A con una estrategia SINGLE_TABLE
  • mapa BB, CC, etc. usando la anotación @SecondaryTable .

No lo he probado, no sé si funcionará bien para BB1, BB2.

Referencia

  • Persistencia de Java con Hibernate
    • 5.1.5 Mezcla de estrategias de herencia (p207-p210)

De acuerdo con la Documentación de referencia de Hibernate , debería ser posible mezclar diferentes estrategias de mapeo de herencia al usar los metadatos XML de Hibernate:
http://docs.jboss.org/hibernate/stable/core/reference/en/html/inheritance.html#inheritance-mixing-tableperclass-tablepersubclass

Sin embargo, la sección correspondiente de la Guía de referencia de anotaciones de Hibernate no cubre eso:
http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e1168

Por otro lado, los JavaDocs sugieren que la mezcla de estrategias de herencia debería ser posible. Por ejemplo, en javax.persistence.DiscriminatorColumn dice:

La estrategia y la columna del discriminador solo se especifican en la raíz de una jerarquía o sub jerarquía de clase de entidad en la que se aplica una estrategia de herencia diferente .

El siguiente es un ejemplo de la asignación que estoy tratando de lograr. Me gustaría utilizar la asignación de tabla por subclase cerca de la raíz de la jerarquía, pero cambiar a la asignación de tabla por jerarquía de clase cerca de las hojas. Aquí hay un código de ejemplo:

@Entity @Inheritance( strategy = InheritanceType.JOINED ) public abstract class A implements Serializable { @Id private String id; // other mapped properties... } @Entity @Inheritance( strategy = InheritanceType.SINGLE_TABLE ) public class BB extends A { // other mapped properties and associations... } @Entity public class BB1 extends BB { // other stuff, not necessarily mapped... } @Entity public class BB2 extends BB { // other stuff, not necessarily mapped... } @Entity @Inheritance( strategy = InheritanceType.SINGLE_TABLE ) public class CC extends A { // other mapped properties and associations... } @Entity public class CC1 extends CC { // other stuff, not necessarily mapped... } ...

Lo que espero de este mapeo es tener exactamente 3 tablas: A , BB y CC . Tanto BB como CC deben tener una columna discriminatoria predeterminada llamada DTYPE . También deben proporcionar todas las columnas necesarias para todas las propiedades mapeadas y las asociaciones de sus respectivas subclases.

En cambio, la jerarquía de clases parece utilizar la estrategia de herencia de tabla por subclase en todo. Es decir, obtengo una tabla propia para cada una de las entidades mencionadas anteriormente. Me gustaría evitar esto, ya que las hojas de la jerarquía de clases son extremadamente livianas y parece demasiado caro tener una tabla separada para cada una de ellas.

¿Pasé por alto algo? ¡Cualquier consejo es muy apreciado! Estaré encantado de proporcionar información adicional ...


En aras de la claridad, aquí está la solución de Pascal aplicada al código de ejemplo de mi pregunta:

@Entity @Inheritance( strategy = InheritanceType.SINGLE_TABLE ) @DiscriminatorColumn( name = "entityType", discriminatorType = DiscriminatorType.STRING ) public abstract class A implements Serializable { @Id private String id; // other mapped properties... } @Entity @SecondaryTable( name = "BB" ) public class BB extends A { @Basic( optional = false) @Column( table = "BB" ) private String property1; // other mapped properties and associations... } @Entity public class BB1 extends BB { // other stuff, not necessarily mapped... } @Entity public class BB2 extends BB { // other stuff, not necessarily mapped... } @Entity @SecondaryTable( name = "CC" ) public class CC extends A { @ManyToOne( optional = false) @JoinColumn( table = "CC" ) private SomeEntity association1; // other mapped properties and associations... } @Entity public class CC1 extends CC { // other stuff, not necessarily mapped... } ...

Apliqué con éxito este enfoque a mi problema, y ​​lo mantendré por el momento. Sin embargo, todavía veo las siguientes desventajas:

  • La columna del discriminador se encuentra en la tabla principal para la jerarquía, la tabla para la raíz-enity A En mi caso, sería suficiente tener la columna del discriminador en las tablas secundarias BB y CC .

  • Cada vez que uno agrega propiedades y asociaciones a subclases de BB o CC , debe especificar que se deben asignar a la tabla secundaria respectiva. Sería bueno, si hubiera una manera de hacer que el valor predeterminado.