
Figura 2.5 Jerarquías entre tablas.
Por naturaleza sabemos que tanto los alumnos como los docentes son personas, por lo que en la tabla personas tendremos los campos comunes a ellos, tales como identificador, número de documento, nombre, apellido, etc., mientras que en las otras tablas tendremos los campos específicos de cada entidad, por ejemplo, los campos sueldo y horas de cátedra para los docentes y número de legajo y fecha de ingreso para los alumnos.
Para poder representar esta situación, emplearemos la herencia de clases: la tabla personas será la clase base y las tablas alumnos y docentes serán subclases de personas.
Para representar la clase Persona, emplearemos la anotación @Inheritance como se observa en el siguiente fragmento de código:
Por el contrario, en Alumno y Docente se debe utilizar la anotación @ PrimaryKeyJoinColumn para especificar cuál es el campo por el cual se va a establecer la relación. El siguiente fragmento de código muestra cómo quedan representadas ambas clases:
2.6 El lenguaje de consultas JPQL
Una de las funciones más importantes dentro de las aplicaciones empresariales es la de acceder a la base de datos a efectos de recuperar registros, procesarlos y presentárselos al usuario. Esta función generalmente se conoce con el nombre de “consultas” o queries.
Como a nivel de aplicación no trabajamos con tablas y registros, sino con entidades y objetos, no podemos utilizar directamente el lenguaje de consultas SQL. En su lugar, debemos buscar alternativas para poder realizar las consultas y convertirlas rápidamente en entidades.
Esa alternativa es JPQL (Jakarta Persistence Query Language) , un lenguaje de consultas similar a SQL pero orientado a objetos. En este esquema, las tablas de una base de datos son representadas como clases (entidades), y los registros (filas), como objetos que se pueden persistir (instancias).
Gracias a este lenguaje, el programador puede abstraerse del lenguaje de consultas del motor de la base de datos y ganar cierto grado de portabilidad, ya que no importaría si la base se implementa con MySQL, MariaDB, PostgreSQL u otro, el programador siempre usaría JPQL.
2.6.1 Estructura y definición de una consulta
JPQL se basa en el uso de cadenas para definir las consultas, y su sintaxis es muy similar a la de SQL. Por ejemplo, para recuperar todos los registros de una tabla llamada personas en SQL, tendríamos lo siguiente:
SELECT * FROM personas;
Su equivalente en JPQL:
SELECT p FROM Persona p;
Con esta cadena de texto obtenemos todas las instancias de la clase Persona. La letra p es una variable que itera sobre los objetos recuperados. Para poder utilizarla dentro de la aplicación, debemos crear una cadena de texto y asignarla a una variable de tipo String.
String consulta = “SELECT p FROM Persona p”;
Luego, se debe pasar como argumento al método createQuery() del EntityManager.
Query query = em.createQuery(consulta);
Por último, para retornar el listado, debemos invocar el método getResultList() de la interface Query.
returnquery.getResultList();
Esto retornará una lista cuyo tipo de dato es Object. Si queremos que sea de tipo Persona o de otro tipo, se deberá realizar la conversión correspondiente mediante el casteo.
return(Persona) query.getResultList();
2.6.2 Consultas parametrizadas
JPQL permite definir dos tipos de parámetros:
* Por posición
* Por nombre
Los parámetros por nombres se representan con el carácter de dos puntos seguido de un nombre que servirá como identificador, por ejemplo: (:codEmpleado)
Los parámetros posicionales se representan con el carácter de interrogación seguido de un número: (?1). Una consulta puede contener más de un parámetro, y un mismo parámetro puede ser utilizado más de una vez en la misma consulta.
Aunque al principio podríamos pensar que los números que siguen al signo de interrogación denotan las posiciones en las que aparecen los parámetros en una expresión, debemos decir que esto no es así, ya que solo representan una referencia (que siempre debe comenzar con el valor 1 y no con un 0).
Ahora, supongamos que necesitamos obtener los datos de un determinado empleado. Para ello, definiremos una consulta que reciba como parámetro de entrada el código de Empleado. En el siguiente ejemplo trabajaremos con parámetros posicionales.
Lo primero que haremos será crear un método buscarEmpleado(), que será público y recibirá como parámetro un código de tipo entero que retornará una instancia de Empleado.
publicEmpleado buscarEmpleado (intcodigo ){…}
Luego, crearemos una cadena para representar la consulta y en ella incluiremos un parámetro posicional ?1, que luego será reemplazado.
String consulta =“SELECT e FROM Empleado e WHERE e.codigo = ?1” ;
Entonces, mediante la interfaz de consultas, la crearemos.
Query q =em .createQuery (consulta );
Para establecer el valor del parámetro, utilizaremos el método setParameter() de la interfaz de consultas: colocaremos el número que corresponde junto al nombre de parámetro que recibe el método.
q .setParameter (1 ,codigo );
Por último, debemos retornar una instancia de tipo Empleado. Como q.getSingleResult() retorna una instancia de tipo Object, es necesario convertir (castear) su tipo a Empleado.
return (Empleado )q .getSingleResult ();
La consulta terminada quedaría del siguiente modo:
La misma consulta pero con parámetros basados en nombres quedaría de la siguiente forma:
2.6.3 Consultas basadas en nombres
Cuando realizamos el mapeo objeto-relacional con la ayuda del asistente de Netbeans, se crea por defecto un conjunto de consultas con la anotación @ NamedQuery.
Por ejemplo, en la entidad Carrera encontramos las siguientes consultas:
A través de ellas podemos listar todas las carreras y buscar una carrera por su nombre o tipo. Pero, ¿qué ocurre si necesitamos obtener o realizar otras consultas y no se encuentran?
Читать дальше