Etiqueta: SqlResultSetMapping
La belleza está en el ojo del espectador. También lo hace «facilidad»:
Obtenga más información sobre las asignaciones de conjuntos de resultados SQL y maneje los resultados de sus consultas nativas con facilidad: http://t.co/WH4BTlClIP #JPA # Java # JavaEE
Thorben escribe artículos muy buenos y útiles sobre JPA, y recientemente ha comenzado una excelente serie sobre las nuevas características de JPA 2.1. Entre los cuales: Mapeo de conjuntos de resultados. Puede conocer la asignación de conjuntos de resultados de sitios web como CTMMC, o annotatiomania.com. Podemos resumir este procedimiento de asignación de la siguiente manera:
a) definir la asignación
@SqlResultSetMapping( name = "BookAuthorMapping", entities = { @EntityResult( entityClass = Book.class, fields = { @FieldResult(name = "id", column = "id"), @FieldResult(name = "title", column = "title"), @FieldResult(name = "author", column = "author_id"), @FieldResult(name = "version", column = "version")}), @EntityResult( entityClass = Author.class, fields = { @FieldResult(name = "id", column = "authorId"), @FieldResult(name = "firstName", column = "firstName"), @FieldResult(name = "lastName", column = "lastName"), @FieldResult(name = "version", column = "authorVersion")})})
La asignación anterior es bastante sencilla. Especifica cómo se deben asignar las columnas de la base de datos a los campos de entidad y a las entidades en su conjunto. A continuación, le da un nombre a esta asignación ("BookAuthorMapping"
), que puede reutilizar en toda la aplicación, por ejemplo, con consultas nativas de JPA.
Me gusta específicamente el hecho de que Thorben escribe:
Si no desea agregar un bloque de anotaciones tan grande a su entidad, también puede definir la asignación en un archivo XML
… Por lo tanto, hemos vuelto a reemplazar grandes bloques de anotaciones por grandes bloques de XML, una técnica que muchos de nosotros queríamos evitar usar anotaciones… :- )
b) aplicar la asignación
Una vez que la asignación se haya definido estáticamente en algún tipo Java, puede obtener esas entidades aplicando lo anterior BookAuthorMapping
List<Object> results = this.em.createNativeQuery( "SELECT b.id, b.title, b.author_id, b.version, " + " a.id as authorId, a.firstName, a.lastName, " + " a.version as authorVersion " + "FROM Book b " + "JOIN Author a ON b.author_id = a.id", "BookAuthorMapping").getResultList();results.stream().forEach((record) -> { Book book = (Book)record; Author author = (Author)record;});
Observe cómo todavía tiene que recordar los tipos Book
y Author
y emitir explícitamente, ya que no hay información de tipo verificable realmente adjunta a nada.
La definición de»complejo «
Ahora, el artículo afirma que esto es una asignación» compleja», y sin duda, estaría de acuerdo. Esta consulta muy simple con solo una unión simple ya desencadena un desorden de anotación si realmente desea mapear sus entidades a través de JPA. No querrá ver las anotaciones de asignación de Thorben, una vez que las consultas se vuelvan un poco más complejas. Y recuerde, @SqlResultSetMapping
se trata de mapear (¡nativo!) Resultados SQL, por lo que ya no estamos en la tierra de persistencia de gráficos de objetos, estamos en la tierra SQL, donde la obtención masiva, la desnormalización, la agregación y otras cosas SQL «sofisticadas» son el rey.
El problema está aquí:
Java 5 introdujo anotaciones. Las anotaciones fueron originalmente pensadas para ser usadas como «modificadores artificiales», es decir, cosas como static
, final
, protected
(curiosamente, Ceilán solo conoce anotaciones, sin modificadores). Esto tiene sentido. Los diseñadores de lenguaje Java podrían introducir nuevos modificadores / » palabras clave «sin romper el código existente, porque las palabras clave» reales » son palabras reservadas, que son difíciles de introducir en un lenguaje. Recuerde enum
?
Por lo tanto, los buenos casos de uso para anotaciones (y solo hay unos pocos) son:
@Override
-
@Deprecated
(aunque, un atributo de comentario hubiera sido elegante) @FunctionalInterface
JPA (y otras API de Java EE, así como Spring) se han vuelto completamente locos en su uso de anotaciones. Repite después de mí:
Ningún lenguaje
@Before
o@After
Java abusó de las anotaciones tanto como Java(la idea de @Antes / @Después era de Lennoff, en reddit)
Hay un fuerte déjà vu en mí al leer lo anterior. ¿Recuerdas lo siguiente?
Ningún lenguaje antes o después de Java abusó de las excepciones comprobadas tanto como Java
Todos lamentaremos profundamente las anotaciones de Java para 2020.
Las anotaciones son una gran verruga en el sistema de tipo Java. Tienen un uso justificado extremadamente limitado y lo que los desarrolladores de Java Enterprise estamos haciendo en estos días no está absolutamente dentro de los límites de «justificado». Estamos abusando de ellos para configurar cosas para las que realmente deberíamos escribir código.
Así es como ejecutaría la misma consulta con jOOQ (o cualquier otra API que aproveche la seguridad de genéricos y tipos para SQL):
Book b = BOOK.as("b");Author a = AUTHOR.as("a");DSL.using(configuration) .select(b.ID, b.TITLE, b.AUTHOR_ID, b.VERSION, a.ID, a.FIRST_NAME, a.LAST_NAME, a.VERSION) .from(b) .join(a).on(b.AUTHOR_ID.eq(a.ID)) .fetch() .forEach(record -> { BookRecord book = record.into(b); AuthorRecord author = record.into(a); });
Este ejemplo combina anotaciones Y consultas de JPA 2.1. Toda la meta información sobre «entidades» proyectadas ya está contenida en la consulta y, por lo tanto, en el Result
que se produce mediante el método fetch()
. Pero realmente no importa, el punto aquí es que esta expresión lambda …
record -> { BookRecord book = record.into(b); AuthorRecord author = record.into(a);}
… puede ser cualquier cosa que quieras! Como los ejemplos más sofisticados que hemos mostrado en publicaciones de blog anteriores:
- Ya no es necesario usar OR
- Transforme sus datos SQL en gráficos Con jOOQ y JavaFX
La asignación se puede definir ad-hoc, sobre la marcha, utilizando funciones. Las funciones son los mapeadores ideales, porque toman una entrada, producen una salida y son completamente apátridas. Y lo mejor de las funciones en Java 8 es que son compiladas por el compilador Java y se pueden usar para verificar el tipo de asignación. Y puede asignar funciones a objetos, lo que le permite reutilizar las funciones, cuando un algoritmo de asignación determinado se puede usar varias veces.
De hecho, la cláusula SQL SELECT
es una función de este tipo. Función que transforma las tuplas / filas de entrada en tuplas / filas de salida y puede adaptar esa función sobre la marcha utilizando expresiones adicionales.
No hay absolutamente ninguna forma de verificar nada en la instrucción SQL nativa JPA 2.1 anterior y en el ejemplo @SqlResultSetMapping
. Imagine cambiar el nombre de una columna:
List<Object> results = this.em.createNativeQuery( "SELECT b.id, b.title as book_title, " + " b.author_id, b.version, " + " a.id as authorId, a.firstName, a.lastName, " + " a.version as authorVersion " + "FROM Book b " + "JOIN Author a ON b.author_id = a.id", "BookAuthorMapping").getResultList();
¿Notaste la diferencia? La columna b.title
se renombró a book_title
. En una cadena SQL. ¡Que explota en tiempo de ejecución! Cómo recordar que también tienes que adaptarte
@FieldResult(name = "title", column = "title")
… para ser
@FieldResult(name = "title", column = "book_title")
Por el contrario, cómo recordar que una vez que cambie el nombre de column
en su @FieldResult
, también tendrá que ir a verificar dónde se usa este "BookAuthorMapping"
, y también cambiar los nombres de columna en esas consultas.
@SqlResultSetMapping( name = "BookAuthorMapping", ...)
Las anotaciones son malas
Puedes o no estar de acuerdo con algunas de las anteriores. Puede que te guste o no jOOQ como alternativa a JPA, eso está perfectamente bien. Pero es realmente difícil estar en desacuerdo con el hecho de que:
- Java 5 introdujo anotaciones muy útiles
- Java EE / Spring abusó mucho de esas anotaciones para reemplazar XML
- Ahora tenemos un sistema de tipo de universo paralelo en Java
- Este sistema de tipo de universo paralelo es completamente inútil porque el compilador no puede hacer introspección
- Java SE 8 introduce programación funcional y mucha inferencia de tipos
- Java SE 9-10 introducirá características de lenguaje más impresionantes
- Ahora queda claro que lo que era la configuración (XML o anotaciones) debería haber sido código en primer lugar
- JPA 2.1 se ha convertido en el nuevo EJB 2.0: Obsoleto
Como he dicho. Es difícil no estar de acuerdo. O en otras palabras:
El código es mucho mejor para expresar algoritmos que la configuración
He conocido personalmente a Thorben en varias ocasiones en conferencias. Esta diatriba de aquí no era personal, Thorben: -) Tus artículos sobre JPA son muy interesantes. Si los lectores de este artículo están usando JPA, por favor revisen el blog de Thorben: http://www.thoughts-on-java.org.
Mientras tanto, me encantaría nominar a Thorben para el respetado título «El Anotador del Año 2015»
Write a Reply or Comment