"mapped-superclass"
. En esta entrada vamos a ver cómo se guardan especializaciones distintas de un mismo tipo pudiendo recuperar todas ellas de forma única o recuperándolas como un tipo específico.En nuestro ejemplo nuestras especializaciones son los distintos tipos de sucesos que hay en un partido (goles, tarjetas, corners, etc...) ya que todos heredan de
Suceso
, en nuestra API concretamente de la implementación SucesoConId
.Para persistir varias clases que heredan de un mismo tipo se puede hacer de tres formas:
SINGLE_TABLE
: Es la opción por defecto y la implementada por todas las librerías. Los datos de todos los subtipos se guardan en una misma tabla. Tiene el mejor rendimiento a la hora de consultar datos porque no hay que realizar ninguna unión, pero como desventaja tendremos camposnull
en las columnas que no usen especificaciones concretas (tienen que existir columnas para todos los campos de todas las implementaciones)JOINED
: Todos los datos comunes se volcarán en una única tabla y el resto de campos se guardará en otra tabla aparte con una FK a la tabla común que lo relacione.TABLE_PER_CLASS
: Esta es una opción de JPA y puede que algunas implementaciones no la contempen. Se trata de guardar cada clase entera en su propia tabla.
SINGLE_TABLE
por ser la más implementada y de mejor rendimiento aunque implique desnormalizar nuestro modelo de datos en la BD.¿Cómo se identifica qué tipo hay en cada fila?
Como vamos a mezclar tipos distintos en la misma tabla debe haber algún mecanismo que permita saber qué tipo concreto hay en cada fila. Para esto, además de todas las columnas para los datos de todas las distintas especializaciones se va a crear una columna que sirva para discriminar el tipo. Para implementar todo lo necesario lo voy a dividir en 4 pasos:- Creación de las dos especializaciones y sus DAO
- ORM por XML para
SucesoConId
y especialización deTarjeta
- ORM por anotaciones de especialización de
Gol
- Modificar nuestro
ObjectMapper
como sea necesario
GolConId
y TarjetaConId
que heredarán de SucesoConId
y además implementarán sus respectivas interfaces (Gol
y Tarjeta
). También vamos a crear los DAO correspondientes como lo hicimos en la sesión anterior sobre Spring Data Rest. Éste código no tiene ningún misterio y se puede ver fácilmente en el commit.Como ya dijimos que para JPA las interfaces no existen, no caigamos en la tentación de asignar las definiciones a las interfaces
Gol
y Tarjeta
(ver fichero Sucesos.orm.xml
): deben ser clases que se puedan instanciar. De hecho podríamos tener implementaciones distintas a GolConId
y TarjetaConId
(y que tuvieran que guardarse de forma distinta también) lo que implicaría otro valor para discriminarlas. Como hay dos especificaciones voy a hacer ORM de formas distintas con cada una:Paso 2:
Tarjeta
por XML (lo añado a SucesoConId.orm.xml
para que se vea que puede haber varias entidades en el mismo fichero):<entity class="es.lanyu.eventos.repositorios.SucesoConId" access="FIELD">
<table name="SUCESOS"/>
<!-- No hace falta strategy es el valor por defecto -->
<inheritance strategy="SINGLE_TABLE"/>
<discriminator-column name="TIPO"/>
<discriminator-value>S</discriminator-value>
<attributes>
...
</attributes>
</entity>
<entity class="es.lanyu.eventos.repositorios.TarjetaConId" access="FIELD">
<discriminator-value>T</discriminator-value>
<attributes>
<basic name="tipoTarjeta"/>
</attributes>
</entity>
Paso 3: Y Gol
lo haré por anotaciones añadiéndole lo que hace falta a la clase GolConId
:@Entity
@Access(value=AccessType.FIELD)
@DiscriminatorValue("G")
public class GolConId extends SucesoConId implements Gol { ... }
NOTA: ver @Access.
Paso 4: Ahora toca tunear nuestro
MixIns
para añadir y reutilizar código (implementación y extensión de ContadorDeMinutos
y refactorizado de Datables-Partidos-Sucesos
). Como no es parte de esta sesión mejor verlo en el commit o el video del webinar.Con esto ya podemos levantar el servicio y empezar a añadir también goles y tarjetas. Veremos que crea URLs para los recursos
/goles
y /tarjetas
donde podemos ver cada uno de ellos por separado o todos juntos en el recurso de /sucesos
pero con relaciones agrupándo cada tipo distinto.Se puede obtener el código hasta aquí en su repositorio. Se han añadido peticiones a la colección de Postman para generar goles y tarjetas aleatorias.
No hay comentarios:
Publicar un comentario