====== Entender y Utilizar los DAS ====== Los DAS son la herramienta que tenemos para facilitar el trabajo con JPA. Es el medio por el cual los servicios realizan las modiciaciones en el contexto de persistencia. Un DAS principalmente tiene que implementar la interface //DataAccessService// y extender la clase //DataAccessServiceImpl//. Vamos a repasar los diferentes métodos que contiene: * En la interface [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/DataAccessService.html|DataAccessService]] tenemos definidos los pricipales métodos para poder crear, borrar, actualizar, refrescar, etc. sobre las entidades. * En la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/DataAccessServiceImpl.html|DataAccessServiceImpl]] tenemos implementados (además de los métodos de la interface) los principales métodos para poder realizar consultas sobre la clase referencia (la identificada como //T//). ===== Implementar un DAS ===== Un DAS esta compuesto por una interface e impementación. ==== Definir la Interface ==== Un DAS tiene que definir una interface que comenzara con el nombre de la clase (entidad o [[https://www.arquitecturajava.com/jpa-dto-data-transfer-object-y-jpql/|DTO]]) que va a manipular. Por ejemplo, si estamos trabajando con la entidad //Anuncio//, el nombre de esta interface será //AnuncioDataAccessService//, en principio el contenido que tendra seran los metodos publicos a exponer a los servicios. También tiene que definir una constante que especifica nombre del componente Seam, que se utilizara en la clase implementación. Este nombre suele ser igual que el nombre de la interface, pero empezando con letra minúscula. La interface del DAS debe extender la interface //DataAccessService//. Ejemplo: package es.um.atica.prueba.security.authorization.das.interfaces; import java.util.List; import es.um.atica.jpa.das.DataAccessService; import es.um.atica.jpa.das.ResultQuery; import es.um.atica.prueba.entities.Anuncio; public interface AnuncioDataAccessService extends DataAccessService { public static final String NAME = "anuncioDataAccessService"; ResultQuery obtenerAnuncios(Map parameters, int firstResult, int resultLimit, String sortField, String sortOrder) } ==== Definir la Implementación ==== La clase implementación del DAS comenzara igual que la interface, pero añadiendo el postfijo //Impl//. En nuestro ejemplo seria //AnuncioDataAccessServiceImpl//. La clase implementación del DAS, debe extender la clase //DataAccessServiceImpl// e implementar la interface creada en el punto anterior (en nuestro ejemplo //DataAccessService//). Ejemplo: package es.um.atica.prueba.security.authorization.das.interfaces; import java.util.List; import javax.ejb.Local; import javax.ejb.Stateless; import org.jboss.seam.annotations.Name; import es.um.atica.jpa.das.DataAccessServiceImpl; import es.um.atica.prueba.entities.Anuncio; @Local( AnuncioDataAccessService.class ) @Stateless @Name( AnuncioDataAccessService .NAME ) public class AnuncioDataAccessServiceImpl extends DataAccessServiceImpl implements AnuncioDataAccessService { // Filtros Dinamicos private static final String[] RESTRICTIONS_ANUNCIO = { UtilString.cmpNumberTextFilterEjbql("entity.id", ":anuncioId"), UtilString.cmpTextFilterEjbql("entity.nombre", ":anuncioNombre"), UtilString.cmpTextFilterEjbql("entity.descripcion", ":anuncioDescripcion"), UtilString.cmpDateTextFilterEjbql("entity.fechaPublicacion", ":anuncioFechaPublicacion"), }; public ResultQuery obtenerAnuncios(Map parameters, int firstResult, int resultLimit, String sortField, String sortOrder) { return super.resultsByEntityQueryWithDinamicFilter(Arrays.asList(RESTRICTIONS_ANUNCIO), parameters, firstResult, resultLimit, sortField, sortOrder, null, null); } } En este ejemplo, hemos hecho un método público (para que sea accedido por un servicio o //LazyDataModel//), que permite hacer consultas páginadas (se devuelven partes de la consulta, donde el primer elemento lo indica el parámetro //firstResult// y el total a devolver el parámetro //resultLimit//. Además, la consulta tiene filtros dinámicos (que aparecen o no en la consulta, dependiendo de si el parámetro es nulo o no). Ejemplo, si el parámetro //parameters// contiene el valor para el parámetro de consulta //anuncioId// (y sólo ese parámetro), en la clausula //WHERE// de la consulta, aparecera la restricción que crea //UtilString.cmpNumberTextFilterEjbql("entity.id", ":anuncioId")//. La consulta JPQL quedaría de la siguiente manera: select entity from Anuncio entity where lower(entity.id) like lower(:anuncioId) En el ejemplo de conulta JPQL anterior, no se ha tenido encuenta aun, los parámetros //firstResult//, //resultLimit//, //sortField// y //sortOrder//. ===== Métodos Disponibles ===== En el DAS tendremos los métodos directos para gestionar la persistencia y métodos para hacer consultas. Muchos ya vienen implementados en la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/DataAccessServiceImpl.html|DataAccessServiceImpl]]. \\ ==== Gestion de la Persistencia ==== En la interface [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/DataAccessService.html|DataAccessService]] tenemos definidos los pricipales métodos para poder crear, borrar, actualizar, refrescar, etc. sobre las entidades. \\ ==== Consultas ==== Tenemos diferenties tipos de métodos para realizar consultas y consultas por defecto definidas. \\ === Consulta por Defecto === Las consultas por defecto la tenemos definidas en las constantes [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/constant-values.html#es.um.atica.jpa.das.DataAccessServiceImpl.ABSTRACT_QUERY|ABSTRACT_QUERY y ABSTRACT_COUNT_QUERY]] de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/DataAccessServiceImpl.html#ABSTRACT_QUERY|DataAccessServiceImpl]]. Esta consulta se puede hacer efectiva mediante los métodos: * //getConcreteQuery()//: es una consulta [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] y devuelve la consulta si utilizamos nuestro ejemplo: **//select entity from Anuncio entity//**. * //getConcreteCountQuery()//: es una consulta [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] y devuelve la consulta si utilizamos nuestro ejemplo: **//select count(*) from Anuncio entity//**. * //getConcreteNativeQuery()//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] y devuelve la consulta si utilizamos nuestro ejemplo: **//select * from Anuncio entity//**. * //getConcreteCountNativeQuery()//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] y devuelve la consulta si utilizamos nuestro ejemplo: **//select count(*) from Anuncio entity//**. Los métodos anteriores, se pueden utilizar por ejemplo, para establecer el parámetro //query// en lo métodos que se explican en los siguientes apartados. También hay que indicar que los métodos que no tienen parámetro //query// o //namedQuery//, utilizan internamente los métodos anteriores, para obtener la consulta por defecto que más se ajusta. Como podeis observar, en las consultas por defecto y en la constante //RESTRICTIONS_ANUNCIO // de la clase de ejemplo //AnuncioDataAccessServiceImpl//, se utiliza el alias //entity//. Este alias se puede cambiar utilizando el método [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/DataAccessServiceImpl.html#setEntityAlias(java.lang.String)|protected void setEntityAlias( String entityAlias )]]. \\ === Métodos que Devuelven una Lista de Objetos === Estos métodos empiezan con el prefijo //find//, despues viene la palabra //By// que indica el tipo de consulta, donde tenemos: * //Query//: es una consulta [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] que devuelve una lista de entidades. * //NativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve una lista de entidades. * //DtoNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve una lista de [[https://www.arquitecturajava.com/jpa-dto-data-transfer-object-y-jpql/|DTOs]] ([[https://www.oracle.com/technetwork/topics/rise-of-the-pojo-088637.html|POJOs]]). * //MapNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve una lista de [[https://docs.oracle.com/javase/7/docs/api/java/util/Map.html|Map]] donde cada clave del mapa, corresponde con una columna del //SELECT// de la consulta. * //NamedQuery//: es una consulta nombrada [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] o [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve una lista de entidades. Las consultas que ejecutan son completas o nombradas. Los métodos de este tipo, que tienen el parámetro //QueryType queryType// en primer lugar, no es necesario utilizarlo, ya que hay otros métodos que cumplen su función. Esos métodos son finales y de uso más interno. \\ === Métodos que Devuelven el Número de Elementos === Parecidos a los anteriores métodos, pero que devuelven el número de elementos de la consulta. Estos métodos empiezan con el prefijo //countTotalRecord//, despues viene la palabra //By// que indica el tipo de consulta, donde tenemos: * //Query//: es una consulta [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] que devuelve el numero de elementos recuperado por la consulta. * //NativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve el numero de elementos recuperado por la consulta. * //NamedQuery//: es una consulta nombrada [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] o [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve el numero de elementos recuperado por la consulta. Los métodos de este tipo, que tienen el parámetro //QueryType queryType// en primer lugar, no es necesario utilizarlo, ya que hay otros métodos que cumplen su función. Esos métodos son finales y de uso más interno. \\ === Métodos que Devuelven una Lista de Objetos con Filtros Dinámicos === Igual que los anteriores pero con filtros dinámicos. Un filtro dinámico es un filtro que se añade a la clausula //WHERE// de la consulta si el parámetro asociado tiene valor, si es nulo, no se añade. Los filtros dinámicos se pasan al método en el parámetro //restrictions//. Estos métodos empiezan con el prefijo //find//, despues viene la palabra //By// que indica el tipo de consulta, donde tenemos: * //EntityQuery//: es una consulta [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] que devuelve una lista de entidades. * //EntityNamedQuery//: es una consulta nombrada [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] (definida mediante [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedQuery.html|@NamedQuery]]) que devuelve una lista de entidades. * //EntityNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve una lista de entidades. * //EntityNamedNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] (definida mediante la [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedNativeQuery.html|@NamedNativeQuery]]) que devuelve una lista de entidades. * //DtoNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve una lista de [[https://www.arquitecturajava.com/jpa-dto-data-transfer-object-y-jpql/|DTOs]] ([[https://www.oracle.com/technetwork/topics/rise-of-the-pojo-088637.html|POJOs]]). * //DtoNamedNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] (definida mediante la [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedNativeQuery.html|@NamedNativeQuery]]) que devuelve una lista de [[https://www.arquitecturajava.com/jpa-dto-data-transfer-object-y-jpql/|DTOs]] ([[https://www.oracle.com/technetwork/topics/rise-of-the-pojo-088637.html|POJOs]]). * //MapNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve una lista de [[https://docs.oracle.com/javase/7/docs/api/java/util/Map.html|Map]] donde cada clave del mapa, corresponde con una columna del //SELECT// de la consulta. * //MapNamedNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve una lista de [[https://docs.oracle.com/javase/7/docs/api/java/util/Map.html|Map]] (definida mediante la [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedNativeQuery.html|@NamedNativeQuery]]) donde cada clave del mapa, corresponde con una columna del //SELECT// de la consulta. Y terminan con el postfijo //WithDinamicFilter//. Los métodos de este tipo, que tienen el parámetro //QueryWithDinamicFilterType queryType// en primer lugar, no es necesario utilizarlo, ya que hay otros métodos que cumplen su función. Esos métodos son finales y de uso más interno. \\ === Métodos que Devuelven el Número de Elementos con Filtros Dinámicos === Parecidos a los anteriores métodos, pero que devuelven el número de elementos de la consulta. Estos métodos empiezan con el prefijo //countTotalRecord//, despues viene la palabra //By// que indica el tipo de consulta, donde tenemos: * //EntityQuery//: es una consulta [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] que devuelve el numero de elementos recuperado por la consulta. * //EntityNamedQuery//: es una consulta nombrada [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] (definida mediante [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedQuery.html|@NamedQuery]]) que devuelve el numero de elementos recuperado por la consulta. * //EntityNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve el numero de elementos recuperado por la consulta. * //EntityNamedNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] (definida mediante la [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedNativeQuery.html|@NamedNativeQuery]]) que devuelve el numero de elementos recuperado por la consulta. * //DtoNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve una lista de [[https://www.arquitecturajava.com/jpa-dto-data-transfer-object-y-jpql/|DTOs]] ([[https://www.oracle.com/technetwork/topics/rise-of-the-pojo-088637.html|POJOs]]) que devuelve el numero de elementos recuperado por la consulta. * //DtoNamedNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] (definida mediante la [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedNativeQuery.html|@NamedNativeQuery]]) que devuelve el numero de elementos recuperado por la consulta. * //MapNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve el numero de elementos recuperado por la consulta. * //MapNamedNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve el numero de elementos recuperado por la consulta. Los métodos de este tipo, que tienen el parámetro //QueryWithDinamicFilterType queryType// en primer lugar, no es necesario utilizarlo, ya que hay otros métodos que cumplen su función. Esos métodos son finales y de uso más interno. \\ === Métodos que Devuelven un objeto ResultQuery con Filtros Dinámicos === Igual que los anteriores con filtros dinámicos, pero que devuelven un objeto de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/ResultQuery.html|ResultQuery]]. Esta clase contiene la lista de objetos y el número de elementos totales de la consulta. Estos métodos empiezan con el prefijo //results//, despues viene la palabra //By// que indica el tipo de consulta, donde tenemos: * //EntityQuery//: es una consulta [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] que devuelve un objeto de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/ResultQuery.html|ResultQuery]] (dentro tiene una lista de entidades). * //EntityNamedQuery//: es una consulta nombrada [[https://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html|JPQL]] (definida mediante [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedQuery.html|@NamedQuery]]) que devuelve un objeto de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/ResultQuery.html|ResultQuery]] (dentro tiene una lista de entidades). * //EntityNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve un objeto de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/ResultQuery.html|ResultQuery]] (dentro tiene una lista de entidades). * //EntityNamedNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] (definida mediante la [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedNativeQuery.html|@NamedNativeQuery]]) que devuelve un objeto de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/ResultQuery.html|ResultQuery]] (dentro tiene una lista de entidades). * //DtoNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve un objeto de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/ResultQuery.html|ResultQuery]] (dentro tiene una lista de [[https://www.arquitecturajava.com/jpa-dto-data-transfer-object-y-jpql/|DTOs]] ([[https://www.oracle.com/technetwork/topics/rise-of-the-pojo-088637.html|POJOs]]). * //DtoNamedNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] (definida mediante la [[https://docs.oracle.com/javaee/6/api/javax/persistence/NamedNativeQuery.html|@NamedNativeQuery]]) que devuelve un objeto de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/ResultQuery.html|ResultQuery]] (dentro tiene una lista de [[https://www.arquitecturajava.com/jpa-dto-data-transfer-object-y-jpql/|DTOs]] ([[https://www.oracle.com/technetwork/topics/rise-of-the-pojo-088637.html|POJOs]]). * //MapNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve un objeto de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/ResultQuery.html|ResultQuery]] (dentro tiene una lista de [[https://docs.oracle.com/javase/7/docs/api/java/util/Map.html|Map]] donde cada clave del mapa, corresponde con una columna del //SELECT// de la consulta). * //MapNamedNativeQuery//: es una consulta [[https://www.oracle.com/database/technologies/appdev/sql.html|SQL Nativa]] que devuelve un objeto de la clase [[https://fundeweb.um.es/prototipo/public/FundeWeb/2.x/apidoc/fundeweb-jpa/es/um/atica/jpa/das/ResultQuery.html|ResultQuery]] (dentro tiene una lista de [[https://docs.oracle.com/javase/7/docs/api/java/util/Map.html|Map]] donde cada clave del mapa, corresponde con una columna del //SELECT// de la consulta). Y terminan con el postfijo //WithDinamicFilter//. Los métodos de este tipo, que tienen el parámetro //QueryWithDinamicFilterType queryType// en primer lugar, no es necesario utilizarlo, ya que hay otros métodos que cumplen su función. Esos métodos son finales y de uso más interno. \\ === Información a Tener en Cuenta === Los parámetros más destacados en los métodos de consulta son: * //query//: de tipo //String//, es la cadena de caracteres con la consulta. * //namedQuery//: de tipo //String//, es el nombre de la consulta nombrada, de la cual obtenemos la cadena de caracteres con la consulta. Si ningúno de los parámetros anteriores aparece, entonces la consulta a ejecutar, es [[fdw2.0:fundeweb2.0:gt:gt-entender-das#consulta_por_defecto|la consulta por defecto]]. * //restrictions//: de tipo //List//, son las restricciones dinámicas a aplicar en la clausula //WHERE// de la consulta. * //parameters//: de tipo //Map parameters//, son los parámetros a aplicar en la consulta. * //firstResult//: de tipo //Integer//, el primer elemento a devolver cuando la consulta página. Por defecto es 0, si es //null// o menor que 0, se aplica el valor por defecto. * //resultLimit//: de tipo //Integer//, el tamaño de la lista a devolver, si es //null// o menor que 1, se ignora. * //sortField//: de tipo //String//, el campo o columna que se utiliza para realizar la ordenación. Ordenación simple. * //sortOrder//: de tipo //String//, el tipo de la ordenación, admite los valores: //ASCENDING//, //ASC//, //DESCENDING//, //DESC// o //UNSORTED//, por defecto //UNSORTED//. Siempre aparece junto al parámetro //sortField//. * //order//: de tipo //String//, contiene la ordenación y el tipo de esta, cuando se ordena por más de un campo o columna. Cada dupla //columna-ordenacion// se separa de la siguiente mediante comas (//,//). Los parámetros //sortField// y //sortOrder//, siempre aparecen juntos. Forman la ordenación simple. El parámetro //order// NUNCA aparece junto con los parámetros //sortField// y //sortOrder//. Se utiliza para la ordenación múltiple. * //logicOperator//: de tipo //String//, contiene el operador logico para las restricciones. Los valores disponibles: //AND// y //OR//, por defecto //AND//. * //hints//: de tipo //Map//, contiene los [[https://thoughts-on-java.org/11-jpa-hibernate-query-hints-every-developer-know/|JPA hints]] de configuración a aplicar a la consulta. * //wherePriority//: de tipo //QueryPriority//, indica que clausula //WHERE// se utiliza en la consulta, cuando esta esta definida tanto en la propia consulta y además definimos filtros dinámicos (en el parámetro //restrictions//). Los valores disponibles son: //QUERY//, //JAVA// y //BOTH//. El valor por defecto //BOTH//. * //orderPriority//: de tipo //QueryPriority//, indica que clausula //ORDER BY// se utiliza en la consulta, cuando esta esta definida tanto en la propia consulta y además en los parámetros (en la dupla de parámetros //sortField// y //sortOrder//, o en el parámetro //order//). Los valores disponibles son: //QUERY//, //JAVA// y //BOTH//. El valor por defecto //JAVA//. * //groupPriority//: de tipo //QueryPriority//, indica que clausula //GROUP BY// se utiliza en la consulta, cuando esta esta definida tanto en la propia consulta y además en los parámetros (en la dupla de parámetros //sortField// y //sortOrder//, o en el parámetro //order//). Los valores disponibles son: //QUERY//, //JAVA// y //BOTH//. El valor por defecto //JAVA//. Los parámetros que son de tipo //QueryPriority//, pueden tener los valores: * //QUERY//: se toma el valor definido en la consulta para configurar la clausula indicada. * //JAVA//: se toma el valor definido en los parámetros del método para configurar la clausula indicada. * //BOTH//: se toma tanto el valor definido en la consulta como el valor definido en los parámetros del método para configurar la clausula indicada. === El Parámetro useWildcardAsCountQuerySubject === El parámetro //useWildcardAsCountQuerySubject// es un valor booleano (valor por defecto //true//), que permite indicar si se utiliza o no el //wildcard *// dentro del //COUNT// al construir la consulta //count// asociada, que es la opción por defecto. Cuando se utilizan clausulas como [[https://thoughts-on-java.org/hibernate-tips-apply-distinct-to-jpql-but-not-sql-query|DISCTINC]] en el //select// de una consulta, si el valor de //useWildcardAsCountQuerySubject// es //true// (que es el valor por defecto), la consulta //count// asociada, devolvera un valor incorrecto. Para obtener el valor correcto en la consulta //count// asociada, tenemos que poner el valor //false// para el parámetro //useWildcardAsCountQuerySubject//, para que dentro de la clausula //COUNT// aparezca lo que tenemos en el //select// de la consulta filtrada. Vamos un ejemplo. La consulta //SELECT a FROM Author a JOIN FETCH a.books// obtiene los autores de los libros, pero si un autor aparece en más de un libro, el autor aparecera repetido en el resultado. La consulta //SELECT DISTINCT a FROM Author a JOIN FETCH a.books// obtiene los autores de los libros, pero si un autor aparece en mas de un libro, solo parece una vez en el resultado. Si el valor del parámetro //useWildcardAsCountQuerySubject// es //true// (valor por defecto) para ambas consultas, la consulta //count// asociada será //SELECT COUNT(*) FROM Author a JOIN FETCH a.books// y devolvera el mismo valor, cuando es evidente que no devuelven el mismo número de elementos. Para la segunda consulta, deberemos poner el valor //false// al parámetro //useWildcardAsCountQuerySubject//. Y obtendremos la consulta //SELECT COUNT(DISTINCT a) FROM Author a JOIN FETCH a.books//, obteniendo el valor correcto. ===== Lecturas Recomendadas ===== * [[fdw2.0:fundeweb2.0:gt:infraestructura_clases_maestro_detalle|Infraestructura de clases Maestro]] * [[fdw2.0:fundeweb2.0:gt:creacion_del_bean_de_respaldo_del_maestro|Creación del Bean de Respaldo del Maestro y clases necesarias]] ---- --- //[[juanmiguel.bernal@ticarum.es|JUAN MIGUEL BERNAL GONZALEZ]] 30/11/2018 09:19//