Java Spring U03
Java Spring U03
Connectivity
Índice de contenidos
Introducción............................................................................................................................................................... 3
Objetivos .................................................................................................................................................................... 3
Un vistazo a las bases de datos............................................................................................................................... 4
Patrón de diseño DAO.............................................................................................................................................. 4
Qué es JDBC .............................................................................................................................................................. 6
Cómo funciona JDBC................................................................................................................................................. 9
Conexión con JDBC .......................................................................................................................................... 9
JDBC con Spring....................................................................................................................................................... 12
JDBC Template......................................................................................................................................................... 15
Aspectos previos............................................................................................................................................ 15
Configurando JdbcTemplate como un bean de Spring............................................................................. 16
Métodos de JdbcTemplate............................................................................................................................ 16
NamedParameters ........................................................................................................................................ 18
JDBC Batch...................................................................................................................................................... 24
Conclusiones ........................................................................................................................................................... 25
Página 2 de 25
Introducción
Todas las aplicaciones, grandes o pequeñas, guardan datos. Ya hemos mencionado que las aplicaciones web
estarán diseñadas en estructuras de tres capas, más adelante hablaremos de las tres, cuando abordemos el
MVC (modelo vista controlador), pero merece la pena pararse a conocer el funcionamiento de la capa de
datos.
Es donde se guardan los datos, es la capa que se encarga de acceder a ellos y proporcionarlos a la capa de
negocio, que hace las operaciones.
Hablaremos de otro patrón de diseño llamado Data Access Object (DAO) e implementaremos la librería
JDBC para acceder a los datos almacenados en una base de datos relacional.
Aprenderás a acceder a una base de datos relacional mediante código Java, para lo que deberás abrir la
conexión, manejar la transacción, obtener o grabar los datos y cerrar la conexión cuando la tarea termine.
Objetivos
Al finalizar esta unidad, serás capaz de...
• Entender el funcionamiento de una base de datos relacional y su integración con los lenguajes
orientados a objetos.
Página 3 de 25
Un vistazo a las bases de datos
La base de datos es el lugar donde se almacenan los datos. Éstos se almacenan de una determinada manera,
y cuando se trata de bases de datos relacionales como las que vamos a manejar, su estructura se basa en
tablas formadas por filas y columnas.
Vamos a pensar en una base de datos de un centro académico que se usa para guardar los datos de los
alumnos. En la base de datos guardamos el nombre, el email, el curso y la fecha de nacimiento de cada alumno.
Además, los cursos estarán guardados en otra tabla y ambas estarán relacionas por el curso al que pertenece
al alumno. Cada vez que un nuevo alumno llega al centro, en secretaría se guardan todos sus datos. Cada
registro se graba en una nueva fila y los datos ocupan una columna en esa fila.
El potencial que tienen las bases de datos es que nos permiten buscar cada registro por el valor de alguno
de sus campos u obtener listas de todos los registros con un campo en común, como puede ser una lista de
los alumnos que pertenecen a determinado curso. No nos puede extrañar que sean una pieza principal en las
aplicaciones.
Existen muchos tipos de bases de datos, que son gestionadas por sistemas gestores de bases de datos
(SGBD) y que usan lenguajes diferentes para modificar, gestionar y recuperar datos que para proporcionar
permisos a usuarios a usuarios y controlar el acceso y la integridad de los datos.
Ya sabemos que los patrones de diseño vienen a solucionar problemas comunes en la programación. Uno
de los problemas más grandes en el momento de acceder a los datos es que la implementación y el formato
pueden variar de una fuente de datos a otra, o incluso en el tiempo, si por cualquier causa se quisiera
cambia la forma de almacenarlos.
La solución pasa por crear un modo de acceder a los datos que se independiente del resto de la aplicación.
Es en ese momento en el que se tiene que construir un puente en el que los datos y la aplicación, es decir la
capa de datos y la capa de negocio se encuentren, además, en ese punto tenemos que hacer que se entiendan
y todo esto teniendo en cuenta que existen muchos tipos de bases de datos muchos lenguajes y muchos
sistemas operativos y herramientas de Java con las que todo esto se maneja. Hemos de pensar siempre en
un modo que sea lo más independientemente posible de todo el hardware y el software en el que tiene que
integrarse. Para que todo este tratamiento no resulte muy engorroso tenemos el patrón de diseño DAO, que
propone separar en dos capas la lógica del negocio y la lógica del acceso a datos.
Resumiendo, entre la capa de negocio y la capa de datos se sitúa la capa DAO que se encarga del acceso
a datos y se usa normalmente para realizar las operaciones conocidas como CRUD (Create, Read, Update y
Delete). La capa DAO se responsabiliza de crear, de obtener, de actualizar y de borrar registros en la base
de datos y mantiene estas operaciones separadas del resto de la lógica del negocio.
Página 4 de 25
Para construir un patrón DAO necesitamos:
Un objeto Java, un objeto POJO, del que ya hemos hablado, es un Plain Old Java Object qué contiene los
atributos constructores y los métodos set y get del objeto.
Una interfaz que defina las operaciones que se puede realizar con el objeto dado.
Página 5 de 25
Qué es JDBC
Java Database Connectivity es una API (interface de aplicaciones) de Java que proporciona una librería
estándar para acceder a fuentes de datos principalmente orientado a bases de datos relacionales que usan
SQL. Es utilizada comúnmente para conectar programas Java con bases de datos usando clases e interfaces
para acceder y gestionar a la base de datos desde código Java.
Realiza las tareas de conectarse a la base de datos, ejecutar consultas SQL y cerrar las conexiones a
la base de datos; su manejo es muy susceptible de generar excepciones, por ello nos veremos obligados a
capturarlas en bloque try catch y manejarlos adecuadamente. Usando la API JDBC el programa será capaz
de enviar sentencias SQL a la base de datos apropiada.
Se trata una interface de bajo nivel, lo que quiere decir que se usa para escribir comandos de SQL
directamente casi como si estuviéramos escribiendo en el propio sistema gestor de base de datos, es decir
no existe lenguaje intermedio, sino que todas las sentencias se escriben en el propio lenguaje SQL, qué es el
lenguaje estándar para el acceso a bases de datos relacionales.
A veces cuando desarrollamos pequeñas aplicaciones, en las que nos vamos a almacenar muchos datos,
podemos utilizar una base de datos embebida en la propia aplicación que se destruirá cuando la aplicación se
cierre.
Esto es muy común en algunas aplicaciones móviles que utilizan por ejemplo una base de datos embebida
que se llama SQLite, otras, en otro tipo de aplicaciones como por ejemplo pueden ser Apache Derby, H2,
etcétera. Nosotros, en este curso, conectaremos una aplicación Java a una base de datos remota, por lo que
necesitaremos comunicarnos con el sistema gestor de base de datos y abrir una conexión desde nuestra
aplicación hasta el servidor que contenga la base de datos.
La API JDBC es compatible con modelos de dos capas y con modelos de tres capas.
Cuando se trata de modelos de dos capas, una aplicación Java se comunica directamente con la base
de datos lo cual requiere un driver que tiene que estar alojado en el mismo lugar en el que está la
aplicación. Desde ahí se envían las sentencias SQL a una base de datos, que puede encontrarse en una
máquina diferente. Se trata de una arquitectura cliente-servidor y el driver es el que se encarga de manejar
las comunicaciones a través de la red.
En el modelo en tres capas los comandos se envían a una capa intermedia qué se encarga de enviar las
sentencias y de recoger los resultados, es decir hay una máquina que tiene el driver y que se sitúa en medio
de la aplicación y la base de datos.
Para que una base de datos se conecte a un programa Java es necesario implementar uno de los tipos de
drivers que tiene JDBC.
JDBC-ODBC Bridge
Se suministra vía drivers ODBC, que son un estándar de acceso a bases de datos desarrollado por Microsoft
y que posibilitan el acceso a cualquier dato desde cualquier aplicación y sin importar el sistema gestor de
base de datos que lo almacene. Es apropiado para una red corporativa.
Página 6 de 25
Native
Está parcialmente escrito en lenguaje java y en código nativo de la base de datos. El driver Java,
parcialmente nativo convierte las llamadas de JDBC en llamadas de la API del cliente, es decir, las propias
del motor de la base de datos por ejemplo Oracle, y eso requiere que cada que esté cargado en la máquina
cliente el Java nativo.
Network
Traduce las llamadas JDBC en llamadas de un protocolo de red, por ejemplo, HTTP, y lo usa para
comunicarse con el servidor de la base de datos. Las llamadas son traducidas por un software intermedio
entonces esto hace que no nos comuniquemos directamente con la base de datos sino a través de ese
software llamado middleware. Es muy útil para aplicaciones que necesitan comunicarse con varios tipos de
datos de bases ya que al final usan el mismo driver para conectarse con todas.
Página 7 de 25
Thin
Controlador java puro que convierte las llamadas JDBC en protocolo nativo usado por el sistema gestor
de la base de datos. Es la solución más práctica para accesos a intranet.
Página 8 de 25
Cómo funciona JDBC
JDBC define varias interfaces destinadas realizar las operaciones con las bases de datos y en realidad están
todas definidas en un paquete llamado java.sql.
Un objeto Connection representa una conexión a la base de datos. La aplicación puede tener varias
conexiones, en realidad todas las que necesite; dentro de la sesión de la conexión se ejecutan las sentencias
SQL y los resultados se devuelven después de la conexión. Además de la posibilidad de tener varias
conexiones con la base de datos.
La forma de establecer la conexión es mediante la llamada a DriverManager. Éste crea la conexión a través
del método getConnection() que contiene contiene como parámetro la cadena URL de la base de datos a la
que queremos conectar.
Lo que ocurre por detrás es que la clase DriverManager tiene una lista de drivers registradas y cuando se
llama al método getConnection busca en cada en cada driver de la lista hasta que encuentra uno que pueda
conectar con la base de datos que especifican en la URL. La URL, Uniforme Resource Locator, es la información
para localizar el recurso en Internet, con protocolo HTTP y se tiene que pensar en ella como si de una
dirección se tratase, en definitiva lo que hace la URL es identificar el lugar en el que está el recurso. Las URLs
de JDBC tienen tres partes:
Página 9 de 25
En la primera parte de esa URL se específica el protocolo usado, sería JDBC.
A continuación, se coloca el subprotocolo, que se refiere al nombre del driver o mecanismo para conectar,
por ejemplo, mysql.
Después, en el subname se encuentra la información para identificar la base de datos y en la que se puede
incluir también el puerto por el que está escuchando, se compone así de hostname:puerto/nombreBD.
GetConnection recibe además dos parámetros más, que son el nombre del usuario y la contraseña.
Después de realizar la conexión se ejecutan las consultas. Para ello utilizamos la interface Statement. Para
conseguir un objeto Statement es necesario llamar al método createStatement que hay disponible dentro
de un objeto Connection. El objeto que se obtiene al crear el Statement tiene los métodos para ejecutar
sentencias SQL.
El objeto Statement tiene varios métodos que usa para realizar las consultas SQL. executeQuery que recibe
una string con la sentencia SQL como parámetro se utiliza para ejecutar sentencias SELECT. Este método
devuelve un objeto ResultSet.
executeUpdate también recibe como parámetro un String con la sentencia SQL pero se utiliza para
sentencias que no devuelven un resultado sino para sentencias de manipulación de datos (DML) como
INSERT, UPDATE y DELETE y para las sentencias de definición de datos (DLL) como CREATE, DROP y ALTER.
En las primeras el método devuelve un entero en el que con el que indica el número de filas que se vieron
afectadas y en las segundas devuelve un 0
execute recibe también un String con la sentencia SQL y devuelve un valor booleano. Se utiliza para para
realizar cualquier consulta SQL, es decir, tanto para las que van a devolver un ResultSet como para las que
devuelve un número de filas afectadas. Devuelve true si devuelve un ResultSet y false si no hay resultado.
Para recuperar las filas o las columnas que se han visto afectadas podemos usar getResultSet y en el caso de
que sea falso se utiliza getUpdateCount para recuperar el valor entero devuelto.
Las sentencias preparadas se crean usando la interface PreparedStatement y crean sentencias SQL que
toman algunos parámetros de entrada.
Es más eficiente que la interface Statement y consiste en colocar signos de interrogación en el lugar de los
Página 10 de 25
parámetros esperados, a cada uno de ellos le corresponde un índice, comenzando por el uno.
La clase PreparedStament tiene setters para todos los tipos básicos de java, y debemos usar el que
corresponda con el tipo de dato que queremos introducir poniendo como parámetros la posición y el valor,
como se indica en el ejemplo anterior. Por otra parte, los procedimientos almacenados en la base de datos se
llaman desde Java con la interface CallableStatement.
Con esta interface se crea un objeto que llama a los procedimientos almacenados. Para crear un objeto se
llama al método prepareCall que recibe un String como parámetro. En ese String se declaran el procedimiento
o la función.
Página 11 de 25
JDBC con Spring
Para conectar la base de datos a una aplicación necesitamos importar las librerías necesarias al empezar
nuestro proyecto.
Creamos una estructura de proyecto similar a las que se encuentran en aplicaciones empresariales, donde
encontraremos separadas las clases de las interfaces y las implementaciones.
Página 12 de 25
La clase Curso será un POJO, con sus atributos de clase privados y los métodos getter y setter públicos.
Tendremos una interface DAO y su implementación, con la que haremos las operaciones en la base de datos.
Página 13 de 25
En la clase principal cargamos el archivo applicationContext, pedimos el bean de la implementación del
DAO y llamamos al método createCurso que grabará el curso que tenemos hardcodeado en la clase
CursoDAOImpl.
Página 14 de 25
JDBC Template
Aspectos previos
JdbcTemplate es la clase central en el paquete JDBC core. Incluye la lógica que usa la API JDBC para
acceder a los datos y es capaz de manejar la conexión crear statement, ejecutarlos y mostrar los resultados.
Se encuentra en el paquete org.springframework.jdbc.core.JdbcTemplate y su utilización nos ayuda a evitar
errores.
1. JdbcTemplate
Constructor sin argumentos, jdbcTemplate(), instanciando el objeto con la palabra reservada new. Después
de ello usaremos el método setDataSource(), para establecer los datos de la conexión.
2. JdbcTemplate(DataSource)
Proporcionando como parámetro un objeto DataSource del que obtener las conexiones.
3. JdbcTemplate(DataSource, boolean)
Proporcionando como parámetro un objeto DataSource del que obtener las conexiones e indicando,
mediante un valor booleano, el modo de iniciar la interface SQLExcpetionTranslator, la cual establece si la
interface se inicia mientras se construye el objeto JdbcTemplate (false) o si lo hace después de que el objeto
sea usado (true).
Por tanto, podemos resumir que la única dependencia que tiene JDBC template es el DataSource que como
ya sabemos, puede estar definido en nuestro archivo applicationContext.xml mediante un Bean y, como
veremos más adelante, en el archivo application properties de nuestro proyecto Spring.
Página 15 de 25
Configurando JdbcTemplate como un bean de Spring
En nuestro fichero XML, al que solemos llamar applicationContext.xml, declaramos el bean después de crear
el dataSource con los datos de la conexión.
Métodos de JdbcTemplate
La clase jdbcTemplate tiene muchos métodos, de los cuales vamos a nombrar los más útiles.
• query= métodos para ejecutar sentencias SQL preparadas con varios parámetros
Algunos ejecutan una acción y no devuelven nada, y otros devuelven una lista de objetos de un determinado
tipo. El ejemplo que sigue devuelve una lista de alumnos, mostrando los campos nombre y edad.
Página 16 de 25
La interfaz RowMapper nos permite mapear el resultado recorriéndolo y añadiéndolo a una colección.
• queryForObject: ejecuta una sentencia proporcionando el tipo de objeto que tiene que recibir.
• queryForList: ejecuta sentencias SELECT que devuelven una lista de objetos del tipo que se
especifica en el argumento.
Página 17 de 25
NamedParameters
NamedParameterJdbcTemplate es una clase que contiene un conjunto de métodos que permiten usar
nombres para los parámetros en lugar de los signos de interrogación. Se puede definir un
NamedParameterJdbcTemplate de la misma manera que un JdbcTemplate, proporcionándole el
DataSource.
Lo usamos también de la misma manera que JdbcTemplate pero en lugar de los interrogantes, en la sentencia
sql, usamos los NamedParametersJdbcTemplate usando RowMapper para mapear el resultado.
Vamos a crear un proyecto con esta estructura como ejemplo de uso de la clase jdbcTemplate.
Página 18 de 25
Si nos fijamos en esta estructura de carpetas en el proyecto vemos que se ha prescindido del archivo
applicationContext.xml. Vamos a realizar todas las inyecciones con las anotaciones @Autowired y vamos a
incluir el schema de la base de datos, de esta manera configuramos la conexión mediante el archivo
application.properties. Este archivo se encuentra en la carpeta resources de los proyectos Spring.
Las properties sirven para proporcionar pares clave-valor que utilizamos en nuestra aplicación y que,
configuradas aquí y de la manera correcta estarán disponibles en toda la aplicación.
Aunque hemos visto que las propiedades pueden definirse en el fichero applicationContext.xml de la manera
La clase Curso.java no cambia de un proyecto a otro, pero en la interface cursoDAO añadimos un método
más para realizar un ejemplo de método con jdbcTemplate, se trata de un método que devuelve el número
de registros que existen en la tabla.
Página 19 de 25
Para implementar esos dos métodos usando la clase jdbcTemplate empezamos declarando una variable
miembro de la clase inyectada con @Autowired. Spring la encontrará dentro del paquete core de su
librería. Además, esta vez no vamos a hardcodear los datos a insertar, los tomaremos de una fuente externa,
para simular el comportamiento real de la aplicación y en el método main le pediremos al usuario que
introduzca el nombre del curso para crear un objeto curso que grabar en la base de datos. También usamos
consultas preparadas y recuperaremos los datos del objeto con su get para insertarlo en la sentencia sql. El
método numFilas nos devolverá el número de registros que hay en la tabla, usando también jdbcTemplate,
y para ver cómo funciona lo llamaremos después de la inserción del curso y verificaremos que está grabado
correctamente, de lo contrario nos lanzaría un mensaje de error.
Para que funcione no podemos olvidar importar el paquete correspondiente, de lo contrario el propio IDE
nos marcará el error y el programa no compilará.
En la clase que contiene el método main implementamos la interface CommandLineRunner para indicarle
al programa que debe ejecutar el método createCurso al arrancar la aplicación.
Dentro de la carpeta DBScript debemos incluir el schema de nuestra base de datos, que tendrá un aspecto
como este.
1.
Página 20 de 25
2.
Página 21 de 25
3.
Página 22 de 25
Para probar el funcionamiento, arrancamos el proyecto. Tal y como está programado en el método, main nos
pedirá que introduzcamos el nombre del curso que queremos grabar, le introducimos el nombre del curso
y pulsamos intro, para que la clase Scanner reconozca la entrada. Si todo es correcto la salida en la consola
será así, y podremos consultar en nuestra base de datos que el curso ha sido grabado.
Página 23 de 25
JDBC Batch
JDBC soporta las ejecuciones Bach las cuales pueden mejorar significativamente el rendimiento de las
aplicaciones cuando intentamos ejecutar varias consultas seguidas. Si tienes en la aplicación diferentes
llamadas con el mismo prepared statement como :
Ahora imagínate que tenemos 100 consultas como estas, en ese caso tenemos que enviarlas todas, una a
una, desde la aplicación Java hasta el servidor que aloja la base de datos a través de la red, lo que generará
una sobrecarga de comunicaciones que podemos reducir si usamos un procesamiento por lotes.
La operación de actualización por lotes permite enviar múltiples consultas SQL para procesar de inmediato,
es decir las agrupa y las ejecuta de forma simultánea . JdbcTemplate incluye dos métodos batchUpdate. Uno
de ellos ejecuta el Bach usando statement SQL usando JDBC statement.
En este código vamos a establecer las notas de los alumnos, asumimos que la nueva columna está creada,
y cambiamos el nombre del curso por el de Spring JDBC ya que dará comienzo otra nueva convocatoria que
tendrá nuevos alumnos.
El otro también ejecuta SQL statement múltiples veces con la diferencia de que usa parámetros usando
consultas preparadas. Asumimos que tenemos en nuestra aplicación una lista de alumnos creada.
Página 24 de 25
Conclusiones
Nuestras aplicaciones manejan datos, cada vez más, que demás se encuentran almacenados en lugares
remotos y precisamos acceder a ellos de una forma rápida y eficaz. El acceso a datos con JDBC existe desde
1996, está incluido en Java desde la versión 1.1. Existen gran cantidad de drivers que permiten conectar a
diferentes sistemas, tanto open source como propietarios.
Al fin y al cabo, un driver es un fichero .jar con la implementación de las interfaces de la API de JDBC, lo
que nos proporciona independencia de la BD con la que trabajemos, esto es, que, si optáramos en un futuro
por otro tipo de base de datos, nuestra aplicación apenas sufriría cambios. Podemos, además, escoger el tipo
de driver que vamos a utilizar.
Spring Framework incluye las clases más útiles para trabajar con bases de datos en las librerías que se
encuentran dentro del paquete core. Hemos aprendido a conectar con una base de datos y a ejecutar
sentencias básicas, tenemos las bases necesarias para empezar a explorar el mundo infinito del acceso a datos.
Página 25 de 25