Download UNIDAD 6 Acceso a Base de Datos usando HIBERNATE PARTE1
Document related concepts
no text concepts found
Transcript
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