Accesa bases de Datos con JDBC y el Patron DAO

Transcripción

Accesa bases de Datos con JDBC y el Patron DAO
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
INTRODUCCION
Los objetos usados en aplicaciones JAVA mantienen su estado y comportamiento mientras la
aplicación se halle en ejecución.
Generalmente se necesita mantener el estado y comportamiento de los objetos utilizados en la
aplicación cuando la aplicación no se está ejecutando en memoria.
Al proceso de mantener el estado y comportamiento de los objetos cuando la aplicación no se halla
en ejecución se denomina PERSISTENCIA DE OBJETOS.
La persistencia de los objetos con JAVA se puede realizar de diversas formas:
•
Usando Serialización: Se utilizan clases que implementan la Interfaz Serializable, para
convertir las clases en una secuencia de cadenas de bytes INDEPENDIENTEMENTE de la
plataforma utilizada. No solo guarda una imagen del objeto sino que también guarda todas
las referencias al objeto.
• Usando bases de datos orientadas a objetos: Las clases se guardan en bases de datos que
permiten almacenar el estado, comportamiento y las propiedades de los objetos.
• Usando bases de datos relacionales (u objeto relacionales) en conjunto con JDBC: Se crean
tablas en las bases de datos relacionales con el objetivo de almacenar el estado de los
objetos. JAVA provee una API denominada JDBC (Java Database Connectivity) que forma
parte del paquete java.sql que permite el acceso a bases de datos de prácticamente todas
las empresas y comunidades más importantes del mercado.
Cuando usamos esta última acción debemos configurar aspectos referidos a:
•
•
•
La conexión y acceso a la bases de datos desde la aplicación
Gestión de información de las tablas de la bases de datos (uso de sentencias SQL)
Mapeo (establecer una correspondencia) de las tablas de la bases de datos con las clases
de la aplicación.
HIBERNATE es un framework que permite la gestión de los 3 aspectos antes mencionados de forma
organizada y casi totalmente automática tal que cuando hacemos una operación de guardar,
modificar, eliminar o consultar el estado de uno o varios objetos, el framework se encarga de generar
las sentencias SQL de forma transparente al programador.
Otra ventaja importante que proporciona HIBERNATE es que permite asegurar que separemos el
código de las clases de la lógica de negocio de las sentencias SQL utilizadas para trabajar con la
Bases de Datos. De esta forma HIBERNATE establece un puente entre la aplicación desarrollada y la
Base de Datos, permitiendo no atarse a una Base de Datos específicas. Además tenemos otra
ventaja adicional muy importante: bien configurado HIBERNATE se encarga de la gestión de los
posibles conflictos que puedan surgir entre los tipos de datos de los atributos de los objetos y los
tipos de datos de las tablas que se mapean con los objetos.
Por si fuera poco aún tenemos otra ventaja importante al usar HIBERNATE, posee un lenguaje
denominado HQL (HIBERNATE Query Language) que permite realizar consultas directamente sobre
los objetos de la aplicación, permitiendo aprovechar algunas de las propiedades de los objetos como
por ejemplo la herencia.
EL ACCESO A BASES DE DATOS USANDO JDBC Y EL PATRON DAO
Antes de utilizar el Framework HIBERNATE debemos realizar una introducción al acceso a bases de
datos relacionales usando JDBC, ya que HIBERNATE usa de soporte JDBC.
Por otro lado se aprovechará para realizar la conexión a la base de datos usando un patrón de
diseño denominado Patron DAO (Data Access Object).
Un patrón de diseño es una solución elegante y probada para diversos problemas comunes. Muchos
programadores se dieron cuenta que diversos problemas de programación son recurrentes, y para
48
Ariel Alejandro Vega
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
ellos existen soluciones similares. Estas soluciones similares fueron probadas por muchos
programadores y derivaron en el nombre de patrones de diseño.
El problema que viene a resolver DAO es el de contar con diversas fuentes de datos (base de datos,
archivos, servicios externos, etc.). De tal forma que se encapsula la forma de acceder a la fuente de
datos. Este patrón surge históricamente de la necesidad de gestionar una diversidad de fuentes de
datos, aunque su uso se extiende al problema de encapsular no sólo la fuente de datos, sino además
ocultar la forma de acceder a los datos. Se trata de que el software cliente se centre en los datos que
necesita y se olvide de cómo se realiza el acceso a los datos o de cuál es la fuente de
almacenamiento.
Las aplicaciones pueden utilizar el API JDBC para acceder a los datos de una base de datos
relacional. Este API permite una forma estándar de acceder y manipular datos en una base de datos
relacional. El API JDBC permite a las aplicaciones JAVA utilizar sentencias SQL, que son el método
estándar para acceder a tablas y vistas.
La idea de este patrón es ocultar la fuente de datos y la complejidad del uso de JDBC a la capa de
presentación o de negocio (en pocas palabras separar las clases que realizan la conexión y las
transacciones en la base de datos, de las clases que reciben o gestionan la información,
colocándolas en otra capa)
Un DAO define la relación entre la lógica de presentación y la del modelo de clases dominio por una
parte y por otra los datos. El DAO tiene un interfaz común, sea cual sea el modo y fuente de acceso a
datos.
•
•
•
•
•
La clase Client representa a una aplicación cualquiera que necesita la información de una o
varias tablas de la base de datos.
La clase DataAccessObject es la encargada de realizar las transacciones SQL usando en
este caso JDBC. Las sentencias SQL se hallan en métodos de esta clase (por ejemplo:
update(), delete(), insert(), getAll())
El DataSource representa la “fuente de datos”, es decir puede representar una o varias
tablas a las cuales el DataAccessObject accede por medio de sus métodos para realizar la
transacción.
La interfaz InterfazDAO define un contrato con DataAccessObject para determinar cuáles
métodos puede poseer este último.
TransferObject es la clase JAVA por medio de la cual podremos obtener los valores desde el
DataSource, o para agregar o modificar clases en el DataSource. Ambas operaciones serán
realizadas por el DataAccessObject.
Algunas características:
•
•
No es imprescindible, pero en proyectos de cierta complejidad resulta útil que el DAO
implemente un interfaz. De esta forma los objetos cliente tienen una forma unificada de
acceder a los DAO.
El DAO accede a la fuente de datos y la encapsula para los objetos clientes. Entendiendo
que oculta tanto la fuente como el modo (JDBC) de acceder a ella.
49
Ariel Alejandro Vega
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
•
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
El TransferObject
erObject encapsula una unidad de información de la fuente de datos. El ejemplo
sencillo es entenderlo como un "bean de tabla", es decir, como una representación de una
tabla de la base de datos, por lo que representamos las columnas de la tabla como atributos
atribu
del TransferObject. El DAO crea un TransferObject (o una colección de ellos) como
consecuencia de una transacción contra la fuente de datos.
Por ejemplo, supongamos que tenemos una tabla de CLIENTES y queremos realizar una consulta de
todos los clientes
es registrados en nuestra aplicación.
•
•
La aplicación actuaría
ía como una clase Client.
Client
Client (la aplicación) posee una clase JAVA que se llama Cliente, cuyos atributos
representan los campos de la tabla CLIENTES.
La clase Cliente actuaría como la clase TransferObject
TransferObject y la tabla CLIENTES como un
DataSource
•
Nosotros creamos una Interfaz que se llame ClienteDAO que posea el método abstracto que
devuelva una lista de objetos TransferObject (Cliente). Es decir que ese método devuelve
tantos TransferObject como registros
r
posea el DataSource (CLIENTES).
Luego creamos una clase llamada ClienteDAOImp que implementa la interfaz ClienteDAO,
por lo tanto OBLIGATORIAMENTE debe poseer el método que devuelve todos los objetos
ob
TransferObject (Cliente) que posee el DataSource
DataSourc (CLIENTES).
En conclusión este método posee toda la lógica para acceder a la base de datos y realizar
una sentencia SQL sobre el DataSource (CLIENTES)
La clase ClienteDAOImp entonces actúa como el objeto DataAccessObject
Entonces, Client solicita a ClienteDaoImp
ClienteDaoImp que ejecute el método que devuelve una lista de
objetos Cliente. Ese método usará JDBC para acceder a la tabla CLIENTES por medio de
una sentencia SQL y los registros devueltos los expresará como objetos Cliente que se
agregarán a la lista de objetos.
objetos. Una vez finalizado esto, la lista de objetos Cliente es
mostrada por ejemplo en una tabla de la aplicación
•
•
Usando JDBC con el patrón DAO
Usando el patrón DAO queda claro que la funcionalidad para el acceso a la base de datos se realiza
en la clase DataAccessObject.
Más específicamente hablando se halla en los métodos que posea el DataAccessObject.
Por otro lado si usamos JAVA y su API JDBC para realizar transacciones en los diversos DataSource
de la base de datos relacional siempre tendremos que realizar
realizar los siguientes pasos:
Requisitos Previos:
•
Poseer e instalar en el proyecto JAVA, el DRIVER JDBC de la Base de Datos a utilizar: El
paquete java.sql de JAVA posee los métodos necesarios para realizar transacciones SQL,
pero la implementación de los mismos
mismos se halla en bibliotecas denominadas DRIVER’S JDBC.
Dado que todas las bases de datos son distintas, sus fabricantes proveen los driver’s JDBC
para poder trabajar con ellas usando JAVA. Practicamente todas las principales empresas
del mercado de bases de
de datos relacionales proveen un driver JDBC. Estos driver’s se
descargan generalmente de la página oficial del proveedor de la base de datos.
50
Ariel Alejandro Vega
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
•
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
Poseer a mano el nombre del DRIVER y la URL para la conexión: Cuando se descarga el
driver JDBC de una base de datos
datos es importante descargar también la documentación. En
dicha documentación se hallan estos dos elementos necesarios. El nombre del Driver nos
sirve para el proceso de registración y uso de la biblioteca del DRIVER (que serán
posteriormente explicados con mayor profundidad). La URL es un cadena de caracteres que
representa el origen de datos (protocolo, puerto, nombre del servidor de datos, versión, etc.).
etc.)
Como se mencionó antes cada fabricante provee su propio DRIVER JDBC por lo tanto
resulta que todos los DRIVER’S poseen distintos nombre y URL.
Pasos para usar JDBC:
A continuación se desarrollará un ejemplo sencillo basado en la tabla CLIENTES para el uso de
JDBC con el patrón DAO para realizar transacciones SQL. En este caso usamos el IDE Netbeans, y
la base de datos a utilizar será la versión Express de ORACLE 10g
Paso 1:: Agregar el DRIVER JDBC al proyecto Netbeans
Una vez que tenemos generados un proyecto debemos seleccionarlo y acceder a la opción
Propiedades (properties). Allí elegimos la categoría bibliotecas (libraries). Luego seleccionamos el
botón Agregar JAR/Carpeta (Add JAR/Folder) y entonces seleccionar la ubicación del DRIVER JDBC
Paso 2: Crear los objetos TransferObject como clases del paquete modelo.dominio
Es común que las clases que representan
representan TransferObject sean las clases importantes de la
aplicación. Generalmente también son las clases que gestionar la lógica de negocio (que es lo que
hace nuestra aplicación).
En JAVA también es común que las clases que gestionan la lógica de negocio se coloquen en el
paquete modelo.dominio ya que el paquete modelo representa la capa de la lógica de negocio de la
aplicación, y las clases que están en el paquete dominio indican que son clases importantes dentro
de la lógica de negocio.
Por lo tanto si nos basamos en la tabla CLIENTES (el DataSource) nosotros necesitamos un
TransferObject que se llame Cliente que represente la tabla CLIENTES.
Un requisito importante para trabajos posteriores es que todos los atributos sean propiedadades (es
decir deben poseer métodos get() y set()).
Por otro lado para el caso de los atributos que sean fechas, debemos usar la clase java.util.Date
como su tipo de datos.
51
Ariel Alejandro Vega
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
Paso 3: Crear las interfaces DAO en el paquete dao
Ya se mencionó antes que el objetivo del patrón DAO es separar las clases de la lógica de negocios
de aquellas que realizan las transacciones en bases de datos. Una forma de reforzar esto es que las
interfaces estén en un paquete que indique que dentro de ellas están las clases que realizan las
transacciones. En este caso para la clase Cliente necesitamos una Interfaz que se llama ClienteDAO
o IclienteDAO. Ambas conveciones son válidas y aceptadas por la comunidad de desarrollo.
Por otro lado esta clase debe poseer las transacciones que vamos a realizar. En primer lugar
ejecutaremos un método que nos permita obtener toda los clientes de la tabla CLIENTES.
Este método lo denominaremos getAll() y devuelve una lista de objetos Cliente.
Paso 3: Crear las clases TransferObject como clases del paquete dao.imp
Necesitamos crear una clase que implemente la interfaz ClienteDAO y que describa el
comportamiento que realizará el método getAll().
Estas clases generalmente se colocan en el paquete imp para separarlas de las interfaces DAO.
Para este caso necesitamos una clase que denominaremos ClienteDAOImp para indicar que es la
implementación de la interfaz ClienteDAO, por otro lado Netbeans nos obligará a que esta clase
posea el método getAll().
52
Ariel Alejandro Vega
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
Paso 4: Usar JDBC dentro de los métodos del DataAccessObject
Nosotros ahora debemos usar JDBC dentro de los métodos del DataAccessObject para poder
ejecutar una sentencia SQL.
Estos son los sub pasos que debemos realizar:
•
Registrar el Driver: Esto permite indicar a la Clase DriverManager que existe un
controlador (DRIVER) que puede usar. Para ello hay dos formas de hacerlo, una es usar la
Class.forName(NOMBRE DEL DRIVER), donde NOMBRE DEL DRIVER es uno de los
requisitos previos antes mencionados. En el caso del Driver de Oracle el nombre es:
oracle.jdbc.OracleDriver
Si el nombre del driver que ingresamos es incorrecto se ejecutará la excepción
ClassNotFoundException
•
Establecer una conexión a la Base de Datos: Para ello usamos Connection y el
controlador registrado usando la clase DriverManager. La clase DriverManager posee un
método getConnection(URL) que permite establecer una conexión a una base de datos
mediante la URL que es uno de los requisitos antes mencionados. En el caso de Oracle la
URL es:
jdbc:oracle:thin:@[SERVIDOR]:[PUERTO]:[SID]
Donde:
SERVIDOR: Es la ubicación y nombre del servidor de bases de datos
PUERTO: Es el puerto por donde escucha el servidor
SID: Es un identificador
53
Ariel Alejandro Vega
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
El método getConnection() puede recibir 1, 2 o 3 parámetros. El primer parámetro siempre es
la URL, el segundo parámetro representa el usuario de bases de datos y el tercero la
contraseña del usuario.
Si nosotros ingresamos mal la URL puede ocurrir una excepción SQLException
•
Crear las sentencias SQL y ejecutarlas: Para ello JDBC nos provee una clase llamada
PreparedStatement a la cual le pasamos la sentencia SQL a ejecutar por medio de la clase
Connection.
Cuando la sentencia SQL que se quiere ejecutar es un SELECT debemos guardar el
resultado de la consulta en un ResultSet. Esta clase almacena una representación del
resultado de la consulta (en este caso sería una representación de la Tabla real)
54
Ariel Alejandro Vega
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
•
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
Transferir el resultado de la sentencia SQL al objeto Client: El objeto Client es quien
solicita la ejecución de una sentencia SQL, es decir que se invoca al método indicado. En
este caso el método invocado es el método getAll(). Este método debe devolver a Client una
lista de objetos Cliente. Por lo tanto debemos transferir el resultado del ResultSet al
ArrayList.
Lo que se hace es recorrer el ResultSet. Para ello usamos el método next() que avanza
sobre un registro del ResultSet y además devuelve true si aún le quedan registros.
Para obtener el valor de un campo de un registro se utiliza el nombre del campo de la
TABLA/S consultada/s y se utiliza el método getTIPO_DE_DATO().
Por ejemplo si queremos obtener el campo cli_nombre, sabemos que este es un
VARCHAR2, por lo tanto el método a usar es getString(“cli_nombre”)
Nota Importante 1: Hay algunos tipos de datos que no existen en el get(). Por ejemplo no
tenemos un getInteger(), pero si tenemos un getInt() que devuelve el entero primitivo,
entonces usando los WRAPPERS lo convertimos a Integer
Nota Importante 2: De la misma forma poseemos un getDate(), pero este devuelve un
objeto java.sql.Date. Si nosotros necesitamos pasarlo a java.util.Date usamos el método
getTime() del objeto java.sql.Date para convertir una fecha a un long y luego lo pasamos al
constructor del objeto java.util.Date.
Nota Importante 3: Finalmente debemos cerrar el ResultSet (si lo usamos), el
PreparedStatement y el Connection. Esto es importante sino sobrecargamos de a poco la
base de datos y al final este puede colapsar.
De esta forma hemos implementado el método getAll() de la clase ClienteDAOImp que realiza la
sentencia SELECT * FROM clientes que devuelve un ArrayList de objetos Cliente usando JDBC y el
patrón DAO.
A continuación se muestra los métodos que permiten realizar las principales transacciones SQL
sobre la tabla CLIENTES
Primero vemos como queda definida la interfaz ClienteDAO
Esto significa que debemos implementar todos los métodos en ClienteDAOImp.
55
Ariel Alejandro Vega
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
SELECT * FROM clientes WHERE cli_codigo = codigo:
Aquí la novedad es que el SELECT posee un filtro que es el código del cliente. Observe que
el valor del código se representa con un signo ? y luego se usa el método
setTIPO_DE_DATO(posición del ?, parámetro)
Donde
TIPO_DE_DATO: es el tipo de dato a usar
Posición del ?: es un número que indica a cual ? estamos pasándole el parámetro
Parámetro: Es la variable por la cual se va a reemplazar el signo ?
INSERT INTO clientes (campos) VALUES (valores):
Aquí la novedad es que en el INSERT pasamos varios signos ? que representan los valores
a asignar. Estos valores los obtenemos de la clase. Por otro lado el método para ejecutar la
sentencia SQL es executeUpdate(). Además no utilizamos un ResultSet.
56
Ariel Alejandro Vega
Programación Orientada a Objetos
Analista Programador Universitario Plan 2008
Año 2010
UNIDAD 6
ACCESO A BASE DE DATOS
HIBERNATE. 1ERA PARTE
UPDATE clientes SET campo1 = valor, campo2: valor2,…:
DELETE FROM clientes WHERE campo1 = valor
57
Ariel Alejandro Vega

Documentos relacionados