Docstoc

API Java de persistencia

Document Sample
API Java de persistencia Powered By Docstoc
					API Java de persistencia
          Aplicaciones web
          y Bases de datos
• Normalmente las aplicaciones web guardan
  datos de distintos tipos, tanto datos
  producidos durante la interacción de los
  usuarios con la aplicación como datos que
  son mostrados a los usuarios.
• Java incluye mecanismos para permitir que
  los programas accedan a bases de datos.
• Java EE también incluye mecanismos
  específicos para hacer más eficiente el
  acceso a bases de datos.
   Servidor de bases de datos
• MySQL Server 5.5
  Usuario: root, Clave: mysql
• Arranque: automático (servicio MySQL)
• Parada:
 C:\Archivos de programa\MySQL\MySQL Server 5.5\bin\
  mysqladmin -uroot -pmysql shutdown
• Administración:
 C:\Archivos de programa\MySQL\MySQL Server 5.5\bin\
 mysqladmin -uroot -pmysql
 Servidor de bases de datos, II
• Acceso desde cliente:
 C:\Archivos de programa\MySQL\MySQL Server 5.5\bin\
 mysql -uroot -pmysql
  – Finalización: quit;
• Bases de datos:
  – CREATE DATABASE CLS;
  – SHOW DATABASES;
  – USE CLS;
• Tablas:
  – SHOW TABLES;
 Servidor de bases de datos, III
• Catálogo:
  information_schema (base de datos)
  – TABLES(TABLE_SCHEMA, TABLE_NAME,
    …)
  – COLUMNS(TABLE_SCHEMA,
    TABLE_NAME, COLUMN_NAME, …)
                 JDBC
• JDBC es una biblioteca de Java que
  permite la conexión a bases de datos
  relacionales.
• JDBC se utiliza mediante un driver que al
  cargarse permite que un programa Java
  se conecte a un servidor de bases de
  datos como un usuario determinado
• JDBC proporciona clases para representar
  las conexiones, consultas SQL y
  resultados de las mismas.
                 JDBC, II
• Un programa Java que utiliza JDBC hace
  lo siguiente:
  – Carga el driver JDBC (la clase que gestiona
    el acceso a bases de datos).
  – Crea una conexión a la base de datos.
  – Crea una consulta en base a código SQL.
  – Ejecuta la consulta, obteniendo un conjunto
    de resultados (o void).
  – Itera si es necesario sobre los resultados.
  – Cierra la conexión.
 Utilización de JDBC mediante la
        API de persistencia
• La API de persistencia, que es parte de JEE
  pero se puede utilizar en otras aplicaciones
  Java, permite la especificación de manera
  sencilla de aplicaciones con un número
  elevado de usuarios simultáneos que acceden
  de manera eficiente a bases de datos.
• Cuando una aplicación Java utiliza la API de
  persistencia (JPA), se crea un pool de
  conexiones JDBC que se reutilizan por los
  distintos hilos de la aplicación.
           JPA: Consultas
• El Lenguaje de Consultas de Persistencia
  de Java (JPQL) permite especificar
  consultas a bases de datos relacionales
  en forma parecida a SQL desde un
  programa Java.
         JPA: Consultas, II
• Los objetos que implementan la interfaz
  TypedQuery<?> de JPA representan
  consultas del tipo anterior.
• Los objetos de la clase anterior que
  representan consultas que devuelven
  valores (tipo SELECT) al ejecutar la
  consultas devuelven listas de objetos.
           Recordatorio:
         Consultas en SQL
• INSERT INTO PERSONA
     VALUES („Pepe‟, „Pérez‟, „inglesa‟)
• SELECT * FROM PERSONA
• UPDATE PERSONA
     SET NACIONALIDAD=„española‟
• DELETE FROM PERSONA
         Consultas en JPQL
• SELECT p FROM Persona p
  – Persona es una entidad (clase)
  – p representa una variable Java de la clase
  – El resultado de la ejecución de la consulta es
    una lista de objetos de la clase
• Se pueden añadir otras cláusulas:
  – SELECT p FROM Persona p
         WHERE p.nombre = „Pepe‟
       Consultas en JPQL, II
• Cuestiones pendientes de estudiar:
  – Programación de consultas
  – Acceso a resultados devueltos por las
    consultas
  – Definición de entidades
  – Sincronización
        JPA: EntityManager
• Para crear y ejecutar consultas mediante
  JPA es necesario crear antes un objeto
  que implementa la interfaz EntityManager,
  que se ocupa de la gestión de los datos y
  de objetos que los representan.
• A continuación veremos cómo se utilizan y
  cómo se crean los EntityManagers.
• Tras esto veremos cómo se definen las
  clases de objetos que representan
  registros de una base de datos.
        JPA: Programación de
              consultas
• Para crear una consulta se utiliza el método
  createQuery de la clase EntityManager, cuyo
  argumento es la cadena de caracteres que
  define la consulta JPQL:
  TypedQuery<Persona> query =
     em.createQuery(
               “SELECT p FROM Persona p”,
               Persona.class);
     JPA: Acceso a resultados
• Para ejecutar una consulta de tipo SELECT
  se utiliza el método getResultList, que
  devuelve una lista de objetos:

 java.util.List<Persona> pers =
                     query.getResultList();
       Gestión de persistencia
             en Java EE
• En Java EE, cuando un contenedor activa un
  objeto, puede inyectar una
  EntityManagerFactory que sea un atributo suyo o
  directamente un EntityManager.
• La inyección directa de EntityManager solamente
  se puede hacer en un contexto monohilo (EJB sin
  estado, beans gestionados de JSF, …).
• La inyección de EntityManagerFactory se puede
  hacer en cualquier contexto (servlet,
  ServletContextListener, página JSP, bean
  gestionado de JSF o EJB).
       Gestión de persistencia
        en Java EE: Ejemplos
• Ejemplo de inyección de E.M.Factory:
  @PersistenceUnit
  private EntityManagerFactory emf;
  EntityManager em =
                   emf.createEntityManager();
• Ejemplo de inyección de EntityManager:
  @PersistenceContext
  EntityManager em;
        Recursos en Java EE
• Los servidores de aplicaciones web permiten el
  acceso a recursos externos como sistemas de
  gestión de bases de datos o de colas de
  mensajes.
• El servidor registra los recursos, asociándoles
  un nombre accesible a través del protocolo
  Java JNDI. El uso de JNDI es transparente.
• La gestión de recursos se puede hacer desde
  NetBeans o desde la aplicación de
  administración del servidor de aplicaciones.
Consideraciones para la utilización
de la API de persistencia en el lab
• Para acceder a una base de datos
  mediante JPA hay que utilizar dos
  recursos: un recurso JDBC y un pool de
  conexiones JDBC.
 Consideraciones para la utilización
de la API de persistencia en el lab, II
• Un pool de conexiones JDBC es un
  conjunto de conexiones JDBC a una base
  de datos disponibles para ser reutilizadas
  concurrentemente por distintos hilos de la
  aplicación.
• Para especificar un pool de conexiones se
  indica la base de datos, usuario,
  contraseña, propiedades, etc.
 Consideraciones para la utilización
de la API de persistencia en el lab, III
• Un recurso JDBC es un proxy a un pool
  de conexiones.
• Para especificar un recurso JDBC hay que
  indicar el nombre con que está registrado
  el pool correspondientes y las
  propiedades.
 Consideraciones para la utilización
de la API de persistencia en el lab, III
• Para crear un recurso JDBC y un
  connection pool en el servidor de
  aplicaciones hay dos posibilidades:
  – Localhost:4848 -> Resources -> JDBC
  – NetBeans -> Proyecto -> New persistence unit
    -> new Data Source -> new Data Base
    connection
  Acceso a recursos JDBC desde
        aplicaciones web
• El fichero de configuración
  persistence.xml permite especificar las
  bases de datos accesibles a una
  aplicación y las entidades que utiliza.
• El fichero de configuración debe incluirse
  en el directorio /META-INF del módulo
  correspondiente.
• La cláusula persistence-unit permite
  especificar un data-source.
 Ejemplo de fichero persistence.xml
<?xml version="1.0" encoding="UTF-8" ?>
<persistence version="1.0"
  xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/...“
  xsi:schemaLocation="http://...">
  <persistence-unit name="book" transaction-type="JTA">
       <jta-data-source>jdbc/__default</jta-data-source>
       <class>com.widgets.Order</class>
       <class>com.widgets.Cust</class>
  </persistence-unit>
</persistence>
             Clases entidad
• Son clases asociadas a tablas (una o varias)
  en una base de datos.
• Sus objetos se asocian a registros.
• Se declaran mediante la anotación @Entity.
• La clave primaria se indica mediante la
  anotación @Id (obligatorio).
• @Entity
  public class Person { @Id int id; … }
          Clases entidad, II
• Si la tabla primaria tiene un nombre
  diferente de la clase, éste se especifica
  mediante la anotación @Table(name).
• NetBeans permite la opción de crear la
  tabla (si no existe) al compilar el código de
  la clase
          Clases entidad, III
• Tipos de atributos:
  – Persistentes (ver próxima transparencia)
  – No persistentes (@Transient)
  – Embebidos (@Embedded), de otra entidad,
    incluidos en la tabla de la primera
  – Generados automáticamente
    (@GeneratedValue)
  – Relaciones (próxima transparencia)
         Clases entidad:
      Atributos persistentes
• Son todos salvo los no persistentes
• Tienen que ser protegidos o privados
• Tipos: Primitivos, wrappers, String,
  temporales (Date, …), arrays de bytes y
  chars, enumeraciones, clases embedibles
• Colecciones: Collection, Set, List, Map
   Definición de entidades en
  persistence.xml (alternativa)
<persistence>
  <persistence-unit name=“…“>
     <jta-data-source>…</jta-data-source>
     …
     <class>com.widgets.Order</class>
     <class>com.widgets.Cust</class>
  </persistence-unit>
</persistence>
       JPA básico: Resumen
• Las clases de entidades representan
  registros de tablas. Se definen mediante la
  anotación @Entity.
• Los recursos JDBC y los pools de
  conexiones se utilizan por el servidor web
  para implementar la conexión a la base de
  datos. Se definen en el servidor.
     JPA básico: Resumen, II
• Los recursos utilizados por una aplicación
  se especifican en el fichero
  persistence.xml.
• Los EntityManagers gestionan el acceso a
  las bases de datos. Se inyectan en un
  objeto gestionado por un contenedor o se
  crean a partir de una fábrica inyectada.
  Están asociados a un recurso JDBC.
    JPA básico: Resumen, III
• Los TypedQuerys pueden ejecutar
  consultas JPA. Se crean a partir de ellas y
  en su caso devuelven listas de entidades.
               Ejercicio
• [DBPERS0] Desarrollar una aplicación
  web que permita ver la lista de personas
  incluidas en una base de datos de
  personas sencilla, como la mencionada en
  los ejemplos anteriores.
      JPA: Programación de
           consultas, II
• Se pueden definir TypedQuerys con tipo
  atómico (Integer, String, etc.) para
  consultas que seleccionan una sola
  columna:
  TypedQuery<String> query =
     em.createQuery(
          “SELECT p.nombre
                FROM Persona p”,
     String.class);
      JPA: Programación de
          consultas, III
• Las consultas de actualización o borrado
  se definen de forma similar:

 UPDATE Persona p
   SET p.nacionalidad=„española‟

 DELETE FROM Persona p
   WHERE p.estado=„fallecido‟
      JPA: Programación de
          consultas, IV
• Para ejecutar una consulta de tipo
  UPDATE o DELETE se utiliza el método
  executeUpdate():

 query.executeUpdate();
        JPA: Programación de
             consultas, V
• Se pueden definir consultas parametrizadas
  utilizando patrones de parámetros:
  TypedQuery<Persona> query=
       em.createQuery(
           “SELECT p FROM Persona p
                WHERE p.edad=?1);
pers = query.setParameter(1, 3).getResultList();
                Ejercicio
• [DBPERS1] Desarrollar una aplicación
  web que permita gestionar a través de
  Internet una base de datos de personas
  sencilla, como la mencionada en los
  ejemplos anteriores, permitiendo dar de
  alta y de baja a personas y modificar sus
  datos.
       Ejercicios voluntarios
• [DBFILE…] Completar los ejercicios de los
  temas anteriores que utilizan ficheros
  (PyCE1, FAV, PyCE2, SWJSF, SWCC,
  AJAXPERS) para guardar sus datos
  sustituyendo los ficheros por una base de
  datos.
      JPA: Programación de
          consultas, VI
• Se pueden utilizar consultas SQL
  (consultas nativas) mediante el método
  createNativeQuery de la clase
  EntityManager.
• El objeto creado por
  EntityManager.createNativeQuery
  implementa la interfaz Query,
  superinterfaz de TypedQuery<?>.
       JPA: Programación de
           consultas, VII
• Los registros obtenidos mediante el
  método Query.getResultList a partir de
  una consulta SQL son arrays de objetos.
• Ejemplo:
  Object[] persona =
     (Object[]) em.createNativeQuery(
           "SELECT * FROM PERSONA”)
                .getResultList().get(0);
  out.println(persona[0] + " " + persona[1]);
        JPA: Programación de
           consultas, VIII
• Se puede determinar el número del registro
  a partir del cual se extraen los resultados y el
  número máximo de resultados a extraer en
  una consulta:

  em.createQuery(
    “SELECT p FROM Persona p”)
         .setFirstResult(5).setMaxResults(9);
       Búsqueda de objetos
           individuales
• Se hace mediante el método
  find(Class<?>, Object) de la clase
  EntityManager.
• Utiliza su segundo argumento como clave
  primaria.
• Ejemplo:
  Person p = e.find(Person.class, 2130);
      Entidades persistentes:
           Ciclo de vida
• Las entidades persistentes pueden estar
  desacopladas de la base de datos o
  acopladas a ella a través de un
  EntityManager. En este caso están en el
  estado Managed (gestionadas).
• Por ejemplo, una entidad persistente
  creada a través de una consulta a la base
  de datos normalmente está gestionada
  por el EntityManager que hace la consulta.
       Entidades persistentes:
           Ciclo de vida, II




           SELECT      Managed
                         (em)



Detached
     Entidades persistentes:
         Ciclo de vida, III
• Una entidad persistente creada mediante
  new está desacoplada de la base de datos
  y se encuentra inicialmente en el estado
  New.
• Si una entidad está en el estado New, en
  la base de datos puede haber un registro
  cuya clave primaria sea la misma de la
  entidad.
       Entidades persistentes:
          Ciclo de vida, IV


New


new        SELECT      Managed
                         (em)



Detached
      Entidades persistentes:
          Ciclo de vida, V
• Las entidades persistentes que están en
  el estado New pueden acoplarse a la base
  de datos mediante el método
  persist(Object) de la clase EntityManager,
  que las gestiona a partir de ese momento
  tras insertar los registros necesarios en la
  base de datos.
• Si en la base de datos ya hay un registro
  con la misma clave primaria, se lanza una
  excepción.
       Entidades persistentes:
          Ciclo de vida, VI

           [Añade registro]
New         em.persist(o)

new        SELECT             Managed
                                (em)



Detached
      Entidades persistentes:
         Ciclo de vida, VII
• Las entidades persistentes gestionadas se
  pueden desacoplar de la base de datos
  mediante el método close(Object) del
  EntityManager que las gestiona, pasando a
  estar en el estado Detached.
• El método merge(Object) de la clase
  EntityManager permite volver a gestionar una
  entidad persistente que está en el estado
  Detached. Tras su ejecución se actualizará la
  base de datos con su contenido.
       Entidades persistentes:
         Ciclo de vida, VIII

               [Añade registro]
New             em.persist(o)

new             SELECT            Managed
                                    (em)
           em.merge(o)
           [objBD]
                  em.close(o)
Detached
      Entidades persistentes:
         Ciclo de vida, IX
• Tanto en el estado New como en Detached
  los cambios que origina el cambio de
  estado de una entidad persistente no se
  trasladan necesariamente a la base de
  datos de inmediato (se hace cuando
  termina la transacción que se está
  ejecutando).
• Lo mismo ocurre con los cambios en los
  valores de los atributos persistentes de las
  entidades gestionadas.
      Entidades persistentes:
          Ciclo de vida, X
• Se puede forzar la realización inmediata
  en la base de datos de los cambios
  pendientes de realizar correspondientes a
  todas las entidades gestionadas por un
  EntityManager mediante el método flush()
  del mismo.
• Esto permite que cualquier otra consulta
  que se haga refleje los cambios realizados
  en las entidades gestionadas por el EM.
       Entidades persistentes:
          Ciclo de vida, XI

               [Añade registro]   [objsBD]
New             em.persist(o)      em.flush()

new             SELECT            Managed
                                    (em)
           em.merge(o)
           [objBD]
                  em.close(o)
Detached
     Entidades persistentes:
        Ciclo de vida, XII
• Las consultas tienen asociado un modo de
  flush, que permite hacer que siempre que
  se ejecuten haya garantías de que la base
  de datos está actualizada con respecto a
  cambios en las entidades gestionadas.
• El modo de flush puede ser AUTO o
  COMMIT.
• Los EntityManagers también tienen un
  modo de flush.
      Entidades persistentes:
        Ciclo de vida, XIII
• La actualización de los registros
  correspondientes a las entidades
  gestionadas por un EntityManager se
  puede hacer mediante una llamada
  explícita al método flush() en el programa
  o lo puede hacer el EntityManager al
  ejecutar acciones previstas en su
  funcionamiento (por ejemplo, cuando se
  termina una transacción).
      Entidades persistentes:
        Ciclo de vida, XIV
• También se puede actualizar una entidad
  acoplada a una base de datos con los
  valores que ésta contiene. Esto se hace
  mediante el método
  EntityManager.refresh(Object).
• Se puede borrar de una base de datos la
  información correspondiente a una entidad
  acoplada a ella, mediante el método remove
  de la clase EntityManager. La entidad pasa
  entonces al estado Removed.
       Entidades persistentes:
          Ciclo de vida, XV
                                   [BD obj]
                                  em.refresh(o)
               [Añade registro]    [objsBD]
New              em.persist(o)      em.flush()

new             SELECT             Managed
                                     (em)
           em.merge(o)
                                         em.remove(o)
           [objBD]
                                       [Elimina registro]
                  em.close(o)
Detached                          Removed
          Gestión de entidades:
            Otros aspectos
• em.setFlushMode(FlushModeType)
      // AUTO (tras ejecución de update)
      // COMMIT (tras finalizar transacción)
• em.lock(Object, LockModeType)
      // READ, WRITE
• em.clear();
  // Desconecta entidades, sin sincronizarlas
• em.close();     // Cierra conexiones
      Relaciones muchos a uno
              Ejemplo
• Tablas:
  – Persona(id int primary key, nombre varchar,
     trabajo int ref Empresa.id)
  – Empresa(id int primary key, nombre varchar)
• Entidades:
  – Persona(@Id int id; String nombre;
    @ManyToOne Empresa trabajo) // Propietario
  – Empresa(@Id int id; String nombre)
 Relaciones muchos a muchos
           Ejemplo
• Tablas:
  – Persona(id int primary key, nombre varchar,
     trabajo int ref Empresa.id)
  – Empresa(id int primary key, nombre varchar)
  – Clientes(idE int ref Empresa.id,
     idP int ref Persona.id
     primary key (idE, idP))
   Relaciones muchos a muchos
            Ejemplo, II
• Entidades:
  – Persona(@Id int id; String nombre;
    @ManyToOne Empresa trabajo)
  – Empresa(@Id int id; String nombre;
    @ManyToMany Set<Persona> clientes) // Prop
• Se podría haber hecho propietaria a la
  entidad Persona. La elección se debe basar
  en criterios de eficiencia.
     Relación uno a muchos
• Relación inversa de otra muchos a uno
• Se implementa por motivos de eficiencia
  (si se va a utilizar con frecuencia)
• Ejemplo:
   Empresa(@Id int id; String nombre;
      @ManyToMany Set<Persona> clientes;
      @OneToMany(mappedBy=“trabajo”)
      Set<Persona> trabajadores)
  Relaciones muchos a muchos:
         Relación inversa
• Se implementa por motivos de eficiencia (si
  se va a utilizar con frecuencia)
• Ejemplo:
  Persona(@Id int id, String nombre;
     @ManyToOne Empresa trabajo;
     @ManyToMany(mappedBy=“clientes”)
     Set<Empresa> contratistas)
        Relaciones uno a uno
• Ejemplo:
  Empresa(…; @OneToOne Persona director)
• En la base de datos una relación uno a uno
  no se distingue de una muchos a uno, salvo
  quizás por una restricción de integridad
• Las relaciones uno a uno se especifican
  mediante la anotación @OneToOne
• La relación inversa de una relación uno a
  uno es también una relación uno a uno
        Consultas y relaciones
• Ejemplos: Empleados de Renfe
  select p from Empresa e JOIN e.clientes p
      where e.name=„Renfe‟
  (lista de Person)
• Para poder hacer una consulta que atraviesa
  una relación, la relación tiene que estar defi-
  nida (en la clase de entidades persistentes)
  en la dirección en la que es atravesada.
           Entidades:
      Jerarquía de herencia

• La API de persistencia incluye varios
  mecanismos para aprovechar la herencia
  que proporciona Java
      Relaciones y gestión de
             entidades
• La API de persistencia permite especificar que las
  acciones de inserción y/o borrado de objetos
  deben propagarse a través de determinadas
  relaciones.
• Para ello se utiliza el atributo cascade de la
  anotación de la relación, cuyos valores pueden
  ser PERSIST, REMOVE o ALL.
• Por ejemplo, si se quieren eliminar los objetos
  relacionados con uno cuando se elimine, se utiliza
  el atributo cascade=REMOVE de la relación
     Relaciones y gestión de
          entidades, II
• Ejemplo, continuación:
  Empresa(@Id int id, String nombre,
     @ManyToMany Set<Persona> clientes,
     @OneToMany(mappedBy=“trabajo”
           cascade=REMOVE)
     Set<Persona> trabajadores)
      Transacciones en SQL
• Una transacción es una secuencia de
  instrucciones SQL que se ejecutan
  provisionalmente, pudiendo anularse en
  cualquier momento o consolidarse al final.
• Por ejemplo, un movimiento en una
  cuenta corriente puede realizarse
  mediante una transacción que comprueba
  que el usuario ha actuado correctamente
  en el cajero automático.
     Transacciones en SQL, II
• En una sesión de ejecución de
  instrucciones en un Sistema de Gestión de
  Bases de Datos cualquier instrucción
  normal comienza una transacción si no hay
  una comenzada.
• La instrucción COMMIT termina una
  transacción dando por buenos los cambios.
• La instrucción ROLLBACK termina una
  transacción deshaciendo los cambios.
   Transacciones en Java EE
• Java EE permite definir transacciones que
  abarcan la ejecución de métodos, de
  manera que si se produce un error tanto
  en el servidor de bases de datos como en
  la máquina virtual se realizan acciones de
  recuperación a un estado seguro.
• Las transacciones son un tema optativo
  en CLS y se estudiarán junto con las
  Enterprise Java Beans (EJB).
Ciclo de vida completo
     de entidades

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:15
posted:9/6/2011
language:Spanish
pages:74