SlideShare ist ein Scribd-Unternehmen logo
1 von 16
Downloaden Sie, um offline zu lesen
CURSO JAVA DEVELOPER - INSTRUCTOR : LEONARDO TORRES ALTEZ


Java Persistence Api


Que es ORM ?
                           JDBC con DAO . Con                                     LINKS DE INTERES :




JPA
                           muchas alternativas         ejecutándose en una
                           incompatibles , el gru-     aplicación Java SE.        ♦ EJB3 : http://www.jcp.org/
                           po Java EE experto                                       en/jsr/detail?id=220
                           toma inspiración de
                           estos frameworks po-        En este articulo , mo-
                                                                                  ♦ JPA API : http://
                           pulares y creo el api de    delare un simple libro
                           persistencia de Java        de direcciones               java.sun.com/javaee/5/
Mapeo Objeto Relacio-      (JPA) , el cual se puede    (Address book ) para         docs/api/javax/
nal (ORM) ,en otras        usar desde aplicaciones     una compañía de músi-        persistence/package-
palabras persistir los     Java EE o SE.               ca ficticia llamada Wa-      summary.html
objetos Java en una                                    termelon , para guardar
base de datos relacio-     En pocas palabras           las direcciones de los     ♦ DAO: http://java.sun.com/
nal - ha tenido su ma-     JPA , usa el modelo de      clientes en la base de       blueprints/
yor cambio reciente-       programación POJO           datos . Watermelon           corej2eepatterns/Patterns/
mente, gracias, en par-    para la persistencia. A     vende y distribuye artí-
                                                                                    DataAccessObject.html
te a la proliferación de   pesar de que este mo-       culos de música así
métodos avanzados          delo esta incluido en la    como instrumentos ,
que intentan hacer esta    especificación EJB 3 ,      amplificadores y li-
tarea mas fácil .          JPA puede ser usado         bros . Voy a usar una
                           fuera de un contenedor      incremental e iterativa
Entre estas tecnologías    EJB , y esta es la forma    aproximación para des-
están los Entity Beans     que será usada en este      arrollar y persistir el
2.x , TopLink , Hiber-     articulo . “Plain Old       modelo del negocio.
nate , JDO , y también     Java Objects” ( POJO )




Como trabaja JPA ?
                           clase y no implemen-
                           tan ninguna interface.
                           Usted no necesita ar-              @Entity
                           chivos descriptores                public class Customer {
                           XML para hacer los
                           mapeos . Si uno se fija              @Id
Inspirado en los frame-    en el API ( java doc )               private Long id;
works como Hiberna-        uno observara que esta               private String firstname;
te , JPA usa anotacio-     compuesto de pocas                   private String lastname;
nes para mapear obje-      clases e interfaces.                 private String telephone;
tos a la base de datos                                          private String email;
relacional. Estos obje-    La mayoría del conteni-              private Integer age;
tos , usualmente llama-    do de el paquete ja-                 // constuctors, getters,
                           vax.persitence son anota-
dos entidades, no tie-                                        setters
                           ciones. Con esto expli-
nen nada en común                                             }
con los Entity Beans       cado , veremos el si-
2.x . Las entidades JPA    guiente ejemplo de
son clases POJOs, no       código :
extienden de ninguna
JAVA PERSISTENCE API                                                                                           Page 2




                                         Lo mínimo necesario ...
                                                                           una clase “Customer” sim-
                                                                           ple . Esta tiene un identifi-
                                                                           cador (id) , un nombre                       El código que sigue mues-
                                                                           ( firstname) , apellido ( last-              tra lo mínimo requerido
                                                                           name) un numero de telé-                     para definir un quot;persistence
                                                                           fono ( telephone ) , mail                    objectquot; . Ahora vamos a
                                                                           ( email ) y edad del cliente                 manipular este objeto,
                                                                           ( age ) . Para ser persistente               deseo persistir mi objeto
                                                                           esta clase tiene que seguir                  “customer” , actualizar algu-
                                                                           algunos reglas JPA simples :                 na de sus propiedades y
                                                                                                                        borrarlo de la base de da-
                                                                           •        La clase tiene que ser identifi-    tos. Estas operaciones serán
                                                                                    cada como una entidad usan-         echas a través de la interfa-
@Entity                                                                             do la anotación
                                                                                                                        ce
public class Customer {                            Esta parte de códi-              @javax.persistence.Entity
                                                   go que vimos                                                         javax.persistence.EntityManager de

                                                   ( constructores ,       •        Una propiedad de la clase           JPA.
     @Id                                                                            tiene que tener un identifica-
                                                   getter y setter no
     private Long id;                              son mostrados para
                                                                                    dor anotado con
                                                                                    @javax.persistence.Id               Para esto, quienes estén
     private String firstname;                     hacer esto mas fácil                                                 familiarizados con el patrón
     private String lastname;                      de leer ) muestra       •        Tiene que haber un construc-        DAO , el EntityManager
     private String telephone;                                                      tor sin argumentos
     private String email;
     private Integer age;
     // constuctors,                               EntityManager ...
     //getters, setters
}                                                  puede ser visto co-     “Customer” ( usando el                       mail usando los métodos
                                                   mo una clase DAO        operador new como cual-                      quot;setquot; .
                                                   que nos provee un       quier otro objeto JAVA ) y
                                                   set de métodos clá-     le pasare algo de data co-                   La interface EntityManger
// métodos CRUD                                    sicos ( persist , re-   mo el quot;idquot; , quot;last namequot; ,                   no tiene un método upda-
                                                   move ) y buscado-       quot;emailquot; , etc. Usare el méto-                te . Los updates se hacen a
public void createCustomer() {
  // Gets an entity manager
                                                   res ( find ).           do EntityManager.persist()                   través de las propiedades
  EntityManagerFactory emf = Persisten-            Después de crear el     para insertar este objeto en                 quot;settersquot; . Luego borrare el
ce.createEntityManagerFactory(quot;watermelonPUquot;);
  EntityManager em = emf.createEntityManager();    EntityManager           la base de datos. Yo puedo                   objeto usando EntityMana-
  EntityTransaction trans = em.getTransaction      usando un factory       luego buscar este objeto                     ger.remove() , notar que
();
                                                   ( EntityManagerFac-     por su identificador usando                  este código usa transaccio-
  // Instantiates a customer object
  Customer customer = new Customer(1L, quot;Johnquot;,
                                                   tory ) , instanciare    el método EntityMan-                         nes explicitas . Es por eso
quot;Lennonquot;, quot;441909quot;, quot;john@lenon.comquot;, 66);         mi objeto               ger.find() y actualizar el                   que los métodos persist ,
    // Persists the customer
    trans.begin();
    em.persist(customer);
    trans.commit();

    // Finds the customer by primary key
                                                   Persistence.xml
    customer = em.find(Customer.class, 1L);
    System.out.println(customer.getEmail());       update , y remove       especifica unidad de persistencia ( watermelonPU en este
    // Updates the customer email address          son llamados entre      caso ) . Una unidad de persistencia es declarada en el ar-
    trans.begin();                                 transacion.begin() y    chivo “persistence.xml” y contiene información como la
    customer.setEmail(quot;john@beatles.co.ukquot;);
    trans.commit();                                transaction.commit      base de datos a usar y el driver JDBC .
    // Deletes the customer                        (). Vea los métodos
    trans.begin();                                 CRUD
    em.remove(customer);                                                   <persistence version=quot;1.0quot; xmlns=quot;http://java.sun.com/xml/ns/persistencequot;>
    trans.commit();
                                                Que base de datos           <persistence-unit name=quot;watermelonPUquot; transaction-type=quot;RESOURCE_LOCALquot;>
    // Closes the entity manager and the factory                             <provider>
    em.close();                                 usamos ? , La res-            oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider
    emf.close();
}                                               puesta esta en Enti-         </provider>
                                                                             <class>entity.Customer</class>
                                                tyManagerFactory,            <properties>
                                                Esta toma un pará-            <property name=quot;toplink.jdbc.urlquot;
                                         metro que se refiere a una                          value=quot;jdbc:mysql://localhost:3306/watermelonDBquot;/>
                                                                              <property name=quot;toplink.jdbc.userquot; value=quot;rootquot;/>
Page 3                                                                             JAVA PERSISTENCE API


Unidad de Persistencia
    <property name=quot;toplink.jdbc.driverquot;   piedades comunes . En este           de la tabla “customer”.
value=quot;com.mysql.jdbc.Driverquot;/>
    <property na-                          caso , estas propiedades
me=quot;toplink.jdbc.passwordquot; value=quot;quot;/>      son : url de la base de da-          Este es el DDL que JPA
    <property name=quot;toplink.target-
databasequot; value=quot;MySQL4quot;/>                 tos , driver JDBC , creden-          gene-
    <property name=quot;toplink.ddl-           ciales. Bajo el elemento             ra
generationquot; value=quot;create-tablesquot;/>
   </properties>
                                           quot;propertiesquot; usted encontra-         auto-
 </persistence-unit>                       ra propiedades especificas
</persistence>
                                           para Top-link por ejemplo
                                           toplink.ddl-generation . Esta
En el código arriba , hay                  propiedad es usada por
solo una unidad de persis-                 TopLink para generar las
tencia , llamada waterme-                  tablas automáticamente si
lonPU ( el archivo persis-                 estas no existen aun . Esto
tence.xml puede contener                   significa que una vez ejecu-
muchas unidades de persis-                 tado el código TopLink a
tencia ) . Usted puede pen-                creado una tabla para guar-          máticamente de la clase
sar en una unidad de per-                  dar la información de                anotada “Customer” . Gra-
sistencia como un conjunto                 “customers”. la tabla 1              cias a la “codificación por
de entidades ( el elemento                 muestra la información DDL           defecto” que guía JPA ( y
class ) que comparten pro-                 ( data definition languaje )         en general Java EE 5 ) No


Customizando
Usted solo necesita añadir                 lumna tiene                          String es mapeado a var-
código customizado cuando                  el mismo                             char(255) ).
el código por defecto es                   nombre de
inadecuado . En mi caso,                   las propie-
porque yo nunca especifico                 dades . Los
el nombre de la tabla o                    tipos de
columnas en la clase                       datos son
“Customer” JPA asume que                   también
el nombre de la tablas es                  mapeados
igual al nombre de la clase                por defecto
y que el nombre de la co-                  ( ejemplo


Añadiendo funcionalidades y customizando el mapeo
En este punto yo quisiera                  primary Key en cuatro posi-                quot;identity generatorquot; ,
                                                                                      ej :una columna definida
mejorar algunas cosas. Pri-                bles modos:                                como auto_increment en
mero que todo, yo no quie-                                                            MySQL.
ro setear un identificador                 •     AUTO (default) permite al
(primary key)del objeto                          proveedor de persistencia
pero en lugar de esto quie-                      (TopLink en mi caso)           Ahora quiero mejorar mi
ro que JPA lo incremente                         decidir cual de las tres       mapeo . Primero cambiar el
                                                 posibilidades usar.            nombre de la tabla a
automáticamente. Gracias a
                                           •     SEQUENCE usar un SQL           quot;t_customerquot; en lugar de
las anotaciones , esto es                        sequence para obtener el
fácil de hacer.                                  próximo primary key
                                                                                quot;customerquot;. Luego hare el
                                                                                nombre ( first name ) y el
                                           •     TABLE requiere una tabla
                                                                                apellido ( last name ) obli-
Solo necesito anotar mi                          con dos columnas : el
atributo identificador                           nombre de la secuencia y       gatorios. El máximo largo
@javax.persitence.GeneratedValue
                                                 su valor ( esta es la estra-   de un numero de teléfono
                                                 tegia por defecto de To-       (telephone) tiene que ser
.                                                pLink )
Esta anotación genera un                                                        15 caracteres y la columna
                                           •      IDENTITY usa un
JAVA PERSISTENCE API                                                                Page 4



                   email tiene que ser renombrada a “e_mail” con un quot;underscorequot; .



                   Todos estos pequeños cambios pueden ser hechos con las anotaciones. Para cambiar el




Una aplicación

puede ser

notificada antes
                   nombre ( name ) de la tabla anote la clase con @javax.persistence.Table . La anotación
o después de       @javax.persistence.Column es usada para definir las columnas y tienen una serie de

ocurridos estos

eventos JPA
                   Anotaciones Callback
usando

quot;callback          Ahora con el mapeo entre la     una entidad es cargada ,        notatios” para mis necesida-
                   clase Customer y la tabla       persistida , actualizada o      des ? , Primero me encarga-
                   t_customer quedo mejor          removida . Una aplicación       re del formato del numero
annotationsquot;
                   gracias a que las anotacio-     puede ser notificada antes o    de teléfono . Quiero verifi-
                   nes @Column y @Table tie-       después de ocurridos estos      car que el primer carácter
                                                                                   del teléfono es quot;+quot; , Yo pue-
                   nen muchos atributos.           eventos usando anotacio-        do hacer esto antes que la
                                                   nes . JPA tiene un conjunto     entidad sea persistida o ac-
                   Hay otras dos cosas que
                                                   de quot;callback annotatiosquot; que    tualizada . solo tengo que
                   quisiera hacer . Primero ase-
                                                   pueden ser usadas en méto-
                   gurarme
                   que todo
                   teléfono es
                   ingresado
                   usando
                   códigos
                   internacio-
                   nales . co-
                   menzando
                   con el sím-
                   bolo '+' .
                                                   dos y permiten al desarrolla-   crear un método ( validateP-
                   Segundo , calcular la edad                                      honeNumber en mi ejem-
                                                   dor añadir cualquier regla
                   del “customer” a partir de                                      plo , pero el nombre es irre-
                                                   de negocios que desee . JPA
                   la fecha de nacimiento .                                        levante ) con algo de lógica
                                                   llamara al método anotado
                   Tengo muchas alternativas                                       de negocios y con las anota-
                                                   antes o después de estos
                   de como hacer estas tareas ,                                    ciones @PrePersist y
                                                   eventos . La tabla 4 muestra    @PreUpdate, JPA hace el
                   pero voy a usar quot;callback
                                                   las quot;callback anotationsquot;       resto.
                   annotationsquot;
                   Durante su ciclo de vida ,      Como uso las “callback an-      El código de ejemplo en la
siguiente pagina.
                                       @PrePersist
                                       @PreUpdate
                     Page 5
                                       private void validatePhoneNumber() {
                                         if (telephone.charAt(0) != '+')
Para la edad del cliente ,                 throw new IllegalArgumentException
hare algo similar, calculare la        (quot;Invalid phone numberquot;);
edad del cliente antes que la            }
fecha de nacimiento sea in-            }
sertada ( @PostPersist ) o
actualizada ( @PostUpdate ) ,
y claro cada vez que el clien-         @PostLoad
te es cargado de la base de            @PostPersist
datos ( @PostLoad ).                   @PostUpdate
                                       public void calculateAge() {
                                           Calendar birth = new GregorianCalendar();
                                           birth.setTime(dateOfBirth);
                                           Calendar now = new GregorianCalendar();
                                           now.setTime(new Date());
                                           int adjust = 0;
                                           if (now.get(Calendar.DAY_OF_YEAR) - birth.get(Calendar.DAY_OF_YEAR) < 0)
                                       {
                                             adjust = -1;
                                           }
                                           age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR) + adjust;
                                       }




Anotaciones Callback .. añadir anotaciones

Para hacer que esto funcio-       TAMP ) . Entonces estoy en      tabla no tendrá una colum-
ne . necesito añadir un nue-      la capacidad de calcular la     na edad mas ) ver tabla 5.
vo atributo a la clase Custo-     edad del cliente pero yo
mer : “date of birth” . Para      necesito persistir esa infor-
notificar a JPA que mapee         mación ? , NO , conociendo
este atributo a una fecha ,       que el valor cambia todos
uso la anotación @Temporal        los años . Para hacer que
con el atributo TemporalTy-       esta propiedad (age) edad
pe.DATE ( las opciones son        no sea persistente , usare la
DATE , TIME , TIMES-              anotación @Transient ( La
JAVA PERSISTENCE API                                                                  Page 6




                    One to One Relationship
                    Ahora que tengo mapeada         Un Customer tiene una y         por su cumpleaños . Lo
                    mi clase Customer y tengo       solo una                        representare como una cla-
                    anotaciones callback para       “address“ (dirección) enton-    se separada, clase Address
                    validar y calcular data , ne-   ces Watermelon pueden           con un id , una calle
                    cesito añadir una dirección.    enviar al cliente un regalo     (street) , una ciudad (city) ,
                                                                                                              un
                                                                                                              có-




   al persistir o

        remover

     “customer”
                    One to One Relationship            public void createCustomerWithAddress() {
 también se hace                                         // Instantiates a Customer and an Address objecy
                                                         Customer customer = new Customer(quot;Johnquot;, quot;Lennonquot;,
                    Como tu pueden ver en la        quot;customer'squot; uso el código
                                                       quot;+441909quot;, quot;john@lenon.comquot;, dateOfBirth);
con su “address”    tabla 6 , la clase Address      que sigue : homeAddress = new Address(quot;Abbey Roadquot;,
                                                         Address
                                                       quot;Londonquot;, quot;SW14quot;, quot;UKquot;);
                    usa la anotación @Entity             customer.setHomeAddress(homeAddress);
                    para notificar a JPA que es
                    una clase persistente y                // Persists the customer with its address
                    @Column para customizar                trans.begin();
                    el mapeo. Creando la rela-             em.persist(homeAddress);
                    ción entre Customer y Ad-              em.persist(customer);
                                                           trans.commit();
                    dress es simple . Yo simple-
                    mente añado una propie-                // Deletes the customer and the address
                    dad Address en la clase                trans.begin();
                    Customer . Para persistir la           em.remove(customer);
                    dirección de los                       em.remove(homeAddress);
                                                           trans.commit();
                                                       }
                    One to One Relationship

                                                    el customer también remue-      por defecto hará las asocia-
                    Como este código muestra ,
                                                    vo el address.                  ciones opcionales y basa-
                    usted tiene primero que
                                                                                    das en mis requerimientos,
                    instanciar un objeto Custo-     Pero persistiendo y remo-
                                                                                    es decir al persistir o remo-
                    mer y un Adress , Para lin-     viendo ambos objetos pare-
                                                                                    ver customer también se
                    kear los dos ,uso un méto-      ce que se hiciera mas traba-
                                                                                    hace con su address.
                    do setter ( set HomeAd-         jo que el que necesito. Se-
                    dress ) y luego persistido      ria mejor si yo pudiera per-
                                                                                    Quiero que un Customer
                    cada objeto , cada uno en       sistir o remover justo el
                                                                                    tenga exactamente un Ad-
                    la misma transacción. Por-      objeto raíz ( el Customer ) y
                                                                                    dress , significa que un va-
                    que no tiene sentido tener      permitir las dependencias
                                                                                    lor null no es permitido .
                    un adress en el sistema que     que se persistan o remue-
                                                                                    Puedo lograr todo eso
                    no este linkeado a un cus-      van automáticamente ? ,
                                                                                    usando la anotación
                    tomer , cuando yo remuevo       TopLink y la codificación
Page 7                                                            JAVA PERSISTENCE API


One to One Relationship
                               loading LAZY) , o               constraint de integri-
@OneToOne es usada para
                               quot;eagerlyquot; (EAGER) porque        dad ,para la relación entre
anotar una relación . Este
                               quiero cargar la dirección      tablas t_customer y t_adress
tiene muchas propiedades
                               de la casa quot;homeAddressquot;        ( ver tabla 7 )
incluyendo un cascade
                               tan pronto como el objeto
usado para quot;cascadingquot; de
                               Customer es cargado.
cualquier tipo de acción. En
este ejemplo , quiero          La anotación @JoinColumn
quot;cascadequot; la acción de per-    tiene los mismos atributos
sistir y remover. De esta      como @Column , excepto
forma , cuando hago remo-      que es usado para asociar
ve o persist de un objeto      atributos , En este ejemplo ,
customer este automática-      Yo renombro la llave forá-
mente lleva acabo esta ac-     nea en un address_fk y no
ción para el quot;addressquot; . El    permito ningún valor null
atributo fetch dice a JPA      ( nullable=false)
que política usar cuando
cargamos una relación.
Esta puede ser una asocia-     JPA entonces creara los                                        El atributo
ción de carga tardía ( lazy    siguientes DDLs con una
                                                                                              fetch dice a JPA

@Entity
                                                                                              que política usar
@Table(name = quot;t_customerquot;)
public class Customer {                                                                       cuando
    @Id                                                                                       cargamos una
    @GeneratedValue
    private Long id;
    (...)                                                                                     relación
    @Transient
    private Integer age;

  @OneToOne(fetch = FetchType.EAGER, cascade =
{CascadeType.PERSIST, CascadeType.REMOVE})
  @JoinColumn(name = quot;address_fkquot;, nullable = false)
  private Address homeAddress;

    // constuctors, getters, setters
}
JAVA PERSISTENCE API                                                                    Page 8




                   Querying Objects
                                                  mite hacer querys comple-   de operadores para filtrar la
                   Hasta ahora yo estoy usan-     jos sobre objetos ( asocia- data ( IN , NOT IN , EXIST , LIKE , IS
                   do JPA para mapear mis         ciones , herencia , clases  NULL , IS NOT NULL ) o para con-
                   objetos a una base de datos abstractas )                   trolar las colecciones ( IS
                   relacional y usar el entity                                EMPTY , IS NOT EMPTY , MEMBER
                   manager para hacer algunas Los querys usan las pala-       OF ) , También hay funcio-
                   operaciones CRUD (Create,      bras SELECT , FROM y        nes para manejar Strings
                                                                              ( LOWER , UPPER , TRIM , CONCAT ,
                   read, update and delete ) ,    WHERE , mas un conjunto                      LENGTH , SUBS-
                   Pero JPA también                                                            TRING ) , nú-
                   permite que hagas     // Finds the customers who are called John
                                                                                               meros ( ABS ,
                   querys sobre los                                                            SQRT , MOD ) , o
                   objetos. Esto usa     Query query = em.createQuery(quot;SELECT c
                                                                                               colecciones
                   quot;Java Persistence     FROM Customer c WHERE                                 ( COUNT , MIN ,
                   Query Langua-         c.firstname='John'quot;);                                 MAX , SUM ). Co-
                   gequot; ( JPQL) , el      List<Customer> customers = que-                       mo SQL , tu
                   cual es similar a     ry.getResultList();                                   también pue-
                   SQL y es también                                                            des ordenar
Usted tiene que    independiente de      // Same query but using a parameter                   los resultados
                   la base de datos ,    //Query query = em.createQuery(quot;SELECT c FROM         ( ORDER BY) o
hacer querys no    Este es un lenguaje //Customer c WHERE c.firstname=:paramquot;);                agruparlos
                                         //query.setParameter(quot;:paramquot;, quot;Johnquot;);               (GROUP BY)
                   rico que nos per-
sobre una tabla,

 mas bien sobre
                   Querying Objects, sobre objetos ...
     un objeto.    Para hacer querys sobre los      dos formas . De cualquiera
                   objetos se necesita Entity-      de las dos formas el string
                   Manager para crear un ob-        quot;Johnquot; es buscado : puede
                   jeto Query . Luego tengo el      ser parte del query JPQL o
                   resultado del query llaman-      puede ser pasado como
                   do el getResultList o gen-       parámetro , en este ultimo
                   SingleResult cuando hay          caso necesito usar el méto-
                   solo un objeto retornado .       do setParameter.
                   En el ejemplo que sigue ,
                   quiero buscar todos los
                   “Customers” quienes tienen
                   el primer nombre quot;Johnquot; ,
                   Yo puedo hacer esto de



                   JPQL Queries, ejemplos ...
                                                    objeto “customer” y el           to address.  SELECT c FROM
                   Como usted puede ver en                                           Customer c WHERE
                   este query JPQL usa la no-       “c.firstname” es la primera
                                                                                     c.homeAddress.country='US';
                   tación objeto . Usted tiene      propiedad del objeto
                   que hacer query no sobre         “customer” . Si ustedes          Acá hay un conjunto de
                   una tabla, mas bien sobre        quieren buscar todos los         querys que nosotros pode-
                   un objeto. El carácter           “customers” que viven en         mos hacer con JPQL . Ver
                   “c” ( el nombre es irrele-       U.S. , ustedes pueden usar       tabla 8
                   vante ) es el alias de un        esta notación , para obtener
                                                    al atributo country del obje-
TopLink Jpa Parte 1 - Leonardo Torres Altez

Weitere ähnliche Inhalte

Ähnlich wie TopLink Jpa Parte 1 - Leonardo Torres Altez

Ähnlich wie TopLink Jpa Parte 1 - Leonardo Torres Altez (20)

Persistencia de datos en Java
Persistencia de datos en JavaPersistencia de datos en Java
Persistencia de datos en Java
 
[ES] Manejadores de persistencia
[ES] Manejadores  de persistencia[ES] Manejadores  de persistencia
[ES] Manejadores de persistencia
 
Jpa
JpaJpa
Jpa
 
Programación en java
Programación en javaProgramación en java
Programación en java
 
Jasperreports
JasperreportsJasperreports
Jasperreports
 
Sesion03 apuntes
Sesion03 apuntesSesion03 apuntes
Sesion03 apuntes
 
Hibernate
HibernateHibernate
Hibernate
 
Java beans en jsp
Java beans en jspJava beans en jsp
Java beans en jsp
 
Java para android developers
Java para android developersJava para android developers
Java para android developers
 
T3 - JPA
T3 - JPAT3 - JPA
T3 - JPA
 
Java.akbc
Java.akbcJava.akbc
Java.akbc
 
Java
JavaJava
Java
 
Curso Java Inicial 2 - Introducción y Sintaxis
Curso Java Inicial  2 - Introducción y SintaxisCurso Java Inicial  2 - Introducción y Sintaxis
Curso Java Inicial 2 - Introducción y Sintaxis
 
SpringFramework Overview
SpringFramework OverviewSpringFramework Overview
SpringFramework Overview
 
Clase n°1 java
Clase n°1 javaClase n°1 java
Clase n°1 java
 
Fondo1 (2)
Fondo1 (2)Fondo1 (2)
Fondo1 (2)
 
C1 java introduccion
C1 java introduccionC1 java introduccion
C1 java introduccion
 
C1 java introduccion
C1 java introduccionC1 java introduccion
C1 java introduccion
 
Clase 1
Clase 1 Clase 1
Clase 1
 
Persistencia De Objetos(Hibernate)
Persistencia De Objetos(Hibernate)Persistencia De Objetos(Hibernate)
Persistencia De Objetos(Hibernate)
 

TopLink Jpa Parte 1 - Leonardo Torres Altez

  • 1. CURSO JAVA DEVELOPER - INSTRUCTOR : LEONARDO TORRES ALTEZ Java Persistence Api Que es ORM ? JDBC con DAO . Con LINKS DE INTERES : JPA muchas alternativas ejecutándose en una incompatibles , el gru- aplicación Java SE. ♦ EJB3 : http://www.jcp.org/ po Java EE experto en/jsr/detail?id=220 toma inspiración de estos frameworks po- En este articulo , mo- ♦ JPA API : http:// pulares y creo el api de delare un simple libro persistencia de Java de direcciones java.sun.com/javaee/5/ Mapeo Objeto Relacio- (JPA) , el cual se puede (Address book ) para docs/api/javax/ nal (ORM) ,en otras usar desde aplicaciones una compañía de músi- persistence/package- palabras persistir los Java EE o SE. ca ficticia llamada Wa- summary.html objetos Java en una termelon , para guardar base de datos relacio- En pocas palabras las direcciones de los ♦ DAO: http://java.sun.com/ nal - ha tenido su ma- JPA , usa el modelo de clientes en la base de blueprints/ yor cambio reciente- programación POJO datos . Watermelon corej2eepatterns/Patterns/ mente, gracias, en par- para la persistencia. A vende y distribuye artí- DataAccessObject.html te a la proliferación de pesar de que este mo- culos de música así métodos avanzados delo esta incluido en la como instrumentos , que intentan hacer esta especificación EJB 3 , amplificadores y li- tarea mas fácil . JPA puede ser usado bros . Voy a usar una fuera de un contenedor incremental e iterativa Entre estas tecnologías EJB , y esta es la forma aproximación para des- están los Entity Beans que será usada en este arrollar y persistir el 2.x , TopLink , Hiber- articulo . “Plain Old modelo del negocio. nate , JDO , y también Java Objects” ( POJO ) Como trabaja JPA ? clase y no implemen- tan ninguna interface. Usted no necesita ar- @Entity chivos descriptores public class Customer { XML para hacer los mapeos . Si uno se fija @Id Inspirado en los frame- en el API ( java doc ) private Long id; works como Hiberna- uno observara que esta private String firstname; te , JPA usa anotacio- compuesto de pocas private String lastname; nes para mapear obje- clases e interfaces. private String telephone; tos a la base de datos private String email; relacional. Estos obje- La mayoría del conteni- private Integer age; tos , usualmente llama- do de el paquete ja- // constuctors, getters, vax.persitence son anota- dos entidades, no tie- setters ciones. Con esto expli- nen nada en común } con los Entity Beans cado , veremos el si- 2.x . Las entidades JPA guiente ejemplo de son clases POJOs, no código : extienden de ninguna
  • 2.
  • 3. JAVA PERSISTENCE API Page 2 Lo mínimo necesario ... una clase “Customer” sim- ple . Esta tiene un identifi- cador (id) , un nombre El código que sigue mues- ( firstname) , apellido ( last- tra lo mínimo requerido name) un numero de telé- para definir un quot;persistence fono ( telephone ) , mail objectquot; . Ahora vamos a ( email ) y edad del cliente manipular este objeto, ( age ) . Para ser persistente deseo persistir mi objeto esta clase tiene que seguir “customer” , actualizar algu- algunos reglas JPA simples : na de sus propiedades y borrarlo de la base de da- • La clase tiene que ser identifi- tos. Estas operaciones serán cada como una entidad usan- echas a través de la interfa- @Entity do la anotación ce public class Customer { Esta parte de códi- @javax.persistence.Entity go que vimos javax.persistence.EntityManager de ( constructores , • Una propiedad de la clase JPA. @Id tiene que tener un identifica- getter y setter no private Long id; son mostrados para dor anotado con @javax.persistence.Id Para esto, quienes estén private String firstname; hacer esto mas fácil familiarizados con el patrón private String lastname; de leer ) muestra • Tiene que haber un construc- DAO , el EntityManager private String telephone; tor sin argumentos private String email; private Integer age; // constuctors, EntityManager ... //getters, setters } puede ser visto co- “Customer” ( usando el mail usando los métodos mo una clase DAO operador new como cual- quot;setquot; . que nos provee un quier otro objeto JAVA ) y set de métodos clá- le pasare algo de data co- La interface EntityManger // métodos CRUD sicos ( persist , re- mo el quot;idquot; , quot;last namequot; , no tiene un método upda- move ) y buscado- quot;emailquot; , etc. Usare el méto- te . Los updates se hacen a public void createCustomer() { // Gets an entity manager res ( find ). do EntityManager.persist() través de las propiedades EntityManagerFactory emf = Persisten- Después de crear el para insertar este objeto en quot;settersquot; . Luego borrare el ce.createEntityManagerFactory(quot;watermelonPUquot;); EntityManager em = emf.createEntityManager(); EntityManager la base de datos. Yo puedo objeto usando EntityMana- EntityTransaction trans = em.getTransaction usando un factory luego buscar este objeto ger.remove() , notar que (); ( EntityManagerFac- por su identificador usando este código usa transaccio- // Instantiates a customer object Customer customer = new Customer(1L, quot;Johnquot;, tory ) , instanciare el método EntityMan- nes explicitas . Es por eso quot;Lennonquot;, quot;441909quot;, quot;john@lenon.comquot;, 66); mi objeto ger.find() y actualizar el que los métodos persist , // Persists the customer trans.begin(); em.persist(customer); trans.commit(); // Finds the customer by primary key Persistence.xml customer = em.find(Customer.class, 1L); System.out.println(customer.getEmail()); update , y remove especifica unidad de persistencia ( watermelonPU en este // Updates the customer email address son llamados entre caso ) . Una unidad de persistencia es declarada en el ar- trans.begin(); transacion.begin() y chivo “persistence.xml” y contiene información como la customer.setEmail(quot;john@beatles.co.ukquot;); trans.commit(); transaction.commit base de datos a usar y el driver JDBC . // Deletes the customer (). Vea los métodos trans.begin(); CRUD em.remove(customer); <persistence version=quot;1.0quot; xmlns=quot;http://java.sun.com/xml/ns/persistencequot;> trans.commit(); Que base de datos <persistence-unit name=quot;watermelonPUquot; transaction-type=quot;RESOURCE_LOCALquot;> // Closes the entity manager and the factory <provider> em.close(); usamos ? , La res- oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider emf.close(); } puesta esta en Enti- </provider> <class>entity.Customer</class> tyManagerFactory, <properties> Esta toma un pará- <property name=quot;toplink.jdbc.urlquot; metro que se refiere a una value=quot;jdbc:mysql://localhost:3306/watermelonDBquot;/> <property name=quot;toplink.jdbc.userquot; value=quot;rootquot;/>
  • 4.
  • 5. Page 3 JAVA PERSISTENCE API Unidad de Persistencia <property name=quot;toplink.jdbc.driverquot; piedades comunes . En este de la tabla “customer”. value=quot;com.mysql.jdbc.Driverquot;/> <property na- caso , estas propiedades me=quot;toplink.jdbc.passwordquot; value=quot;quot;/> son : url de la base de da- Este es el DDL que JPA <property name=quot;toplink.target- databasequot; value=quot;MySQL4quot;/> tos , driver JDBC , creden- gene- <property name=quot;toplink.ddl- ciales. Bajo el elemento ra generationquot; value=quot;create-tablesquot;/> </properties> quot;propertiesquot; usted encontra- auto- </persistence-unit> ra propiedades especificas </persistence> para Top-link por ejemplo toplink.ddl-generation . Esta En el código arriba , hay propiedad es usada por solo una unidad de persis- TopLink para generar las tencia , llamada waterme- tablas automáticamente si lonPU ( el archivo persis- estas no existen aun . Esto tence.xml puede contener significa que una vez ejecu- muchas unidades de persis- tado el código TopLink a tencia ) . Usted puede pen- creado una tabla para guar- máticamente de la clase sar en una unidad de per- dar la información de anotada “Customer” . Gra- sistencia como un conjunto “customers”. la tabla 1 cias a la “codificación por de entidades ( el elemento muestra la información DDL defecto” que guía JPA ( y class ) que comparten pro- ( data definition languaje ) en general Java EE 5 ) No Customizando Usted solo necesita añadir lumna tiene String es mapeado a var- código customizado cuando el mismo char(255) ). el código por defecto es nombre de inadecuado . En mi caso, las propie- porque yo nunca especifico dades . Los el nombre de la tabla o tipos de columnas en la clase datos son “Customer” JPA asume que también el nombre de la tablas es mapeados igual al nombre de la clase por defecto y que el nombre de la co- ( ejemplo Añadiendo funcionalidades y customizando el mapeo En este punto yo quisiera primary Key en cuatro posi- quot;identity generatorquot; , ej :una columna definida mejorar algunas cosas. Pri- bles modos: como auto_increment en mero que todo, yo no quie- MySQL. ro setear un identificador • AUTO (default) permite al (primary key)del objeto proveedor de persistencia pero en lugar de esto quie- (TopLink en mi caso) Ahora quiero mejorar mi ro que JPA lo incremente decidir cual de las tres mapeo . Primero cambiar el posibilidades usar. nombre de la tabla a automáticamente. Gracias a • SEQUENCE usar un SQL quot;t_customerquot; en lugar de las anotaciones , esto es sequence para obtener el fácil de hacer. próximo primary key quot;customerquot;. Luego hare el nombre ( first name ) y el • TABLE requiere una tabla apellido ( last name ) obli- Solo necesito anotar mi con dos columnas : el atributo identificador nombre de la secuencia y gatorios. El máximo largo @javax.persitence.GeneratedValue su valor ( esta es la estra- de un numero de teléfono tegia por defecto de To- (telephone) tiene que ser . pLink ) Esta anotación genera un 15 caracteres y la columna • IDENTITY usa un
  • 6.
  • 7. JAVA PERSISTENCE API Page 4 email tiene que ser renombrada a “e_mail” con un quot;underscorequot; . Todos estos pequeños cambios pueden ser hechos con las anotaciones. Para cambiar el Una aplicación puede ser notificada antes nombre ( name ) de la tabla anote la clase con @javax.persistence.Table . La anotación o después de @javax.persistence.Column es usada para definir las columnas y tienen una serie de ocurridos estos eventos JPA Anotaciones Callback usando quot;callback Ahora con el mapeo entre la una entidad es cargada , notatios” para mis necesida- clase Customer y la tabla persistida , actualizada o des ? , Primero me encarga- t_customer quedo mejor removida . Una aplicación re del formato del numero annotationsquot; gracias a que las anotacio- puede ser notificada antes o de teléfono . Quiero verifi- nes @Column y @Table tie- después de ocurridos estos car que el primer carácter del teléfono es quot;+quot; , Yo pue- nen muchos atributos. eventos usando anotacio- do hacer esto antes que la nes . JPA tiene un conjunto entidad sea persistida o ac- Hay otras dos cosas que de quot;callback annotatiosquot; que tualizada . solo tengo que quisiera hacer . Primero ase- pueden ser usadas en méto- gurarme que todo teléfono es ingresado usando códigos internacio- nales . co- menzando con el sím- bolo '+' . dos y permiten al desarrolla- crear un método ( validateP- Segundo , calcular la edad honeNumber en mi ejem- dor añadir cualquier regla del “customer” a partir de plo , pero el nombre es irre- de negocios que desee . JPA la fecha de nacimiento . levante ) con algo de lógica llamara al método anotado Tengo muchas alternativas de negocios y con las anota- antes o después de estos de como hacer estas tareas , ciones @PrePersist y eventos . La tabla 4 muestra @PreUpdate, JPA hace el pero voy a usar quot;callback las quot;callback anotationsquot; resto. annotationsquot; Durante su ciclo de vida , Como uso las “callback an- El código de ejemplo en la
  • 8.
  • 9. siguiente pagina. @PrePersist @PreUpdate Page 5 private void validatePhoneNumber() { if (telephone.charAt(0) != '+') Para la edad del cliente , throw new IllegalArgumentException hare algo similar, calculare la (quot;Invalid phone numberquot;); edad del cliente antes que la } fecha de nacimiento sea in- } sertada ( @PostPersist ) o actualizada ( @PostUpdate ) , y claro cada vez que el clien- @PostLoad te es cargado de la base de @PostPersist datos ( @PostLoad ). @PostUpdate public void calculateAge() { Calendar birth = new GregorianCalendar(); birth.setTime(dateOfBirth); Calendar now = new GregorianCalendar(); now.setTime(new Date()); int adjust = 0; if (now.get(Calendar.DAY_OF_YEAR) - birth.get(Calendar.DAY_OF_YEAR) < 0) { adjust = -1; } age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR) + adjust; } Anotaciones Callback .. añadir anotaciones Para hacer que esto funcio- TAMP ) . Entonces estoy en tabla no tendrá una colum- ne . necesito añadir un nue- la capacidad de calcular la na edad mas ) ver tabla 5. vo atributo a la clase Custo- edad del cliente pero yo mer : “date of birth” . Para necesito persistir esa infor- notificar a JPA que mapee mación ? , NO , conociendo este atributo a una fecha , que el valor cambia todos uso la anotación @Temporal los años . Para hacer que con el atributo TemporalTy- esta propiedad (age) edad pe.DATE ( las opciones son no sea persistente , usare la DATE , TIME , TIMES- anotación @Transient ( La
  • 10.
  • 11. JAVA PERSISTENCE API Page 6 One to One Relationship Ahora que tengo mapeada Un Customer tiene una y por su cumpleaños . Lo mi clase Customer y tengo solo una representare como una cla- anotaciones callback para “address“ (dirección) enton- se separada, clase Address validar y calcular data , ne- ces Watermelon pueden con un id , una calle cesito añadir una dirección. enviar al cliente un regalo (street) , una ciudad (city) , un có- al persistir o remover “customer” One to One Relationship public void createCustomerWithAddress() { también se hace // Instantiates a Customer and an Address objecy Customer customer = new Customer(quot;Johnquot;, quot;Lennonquot;, Como tu pueden ver en la quot;customer'squot; uso el código quot;+441909quot;, quot;john@lenon.comquot;, dateOfBirth); con su “address” tabla 6 , la clase Address que sigue : homeAddress = new Address(quot;Abbey Roadquot;, Address quot;Londonquot;, quot;SW14quot;, quot;UKquot;); usa la anotación @Entity customer.setHomeAddress(homeAddress); para notificar a JPA que es una clase persistente y // Persists the customer with its address @Column para customizar trans.begin(); el mapeo. Creando la rela- em.persist(homeAddress); ción entre Customer y Ad- em.persist(customer); trans.commit(); dress es simple . Yo simple- mente añado una propie- // Deletes the customer and the address dad Address en la clase trans.begin(); Customer . Para persistir la em.remove(customer); dirección de los em.remove(homeAddress); trans.commit(); } One to One Relationship el customer también remue- por defecto hará las asocia- Como este código muestra , vo el address. ciones opcionales y basa- usted tiene primero que das en mis requerimientos, instanciar un objeto Custo- Pero persistiendo y remo- es decir al persistir o remo- mer y un Adress , Para lin- viendo ambos objetos pare- ver customer también se kear los dos ,uso un méto- ce que se hiciera mas traba- hace con su address. do setter ( set HomeAd- jo que el que necesito. Se- dress ) y luego persistido ria mejor si yo pudiera per- Quiero que un Customer cada objeto , cada uno en sistir o remover justo el tenga exactamente un Ad- la misma transacción. Por- objeto raíz ( el Customer ) y dress , significa que un va- que no tiene sentido tener permitir las dependencias lor null no es permitido . un adress en el sistema que que se persistan o remue- Puedo lograr todo eso no este linkeado a un cus- van automáticamente ? , usando la anotación tomer , cuando yo remuevo TopLink y la codificación
  • 12.
  • 13. Page 7 JAVA PERSISTENCE API One to One Relationship loading LAZY) , o constraint de integri- @OneToOne es usada para quot;eagerlyquot; (EAGER) porque dad ,para la relación entre anotar una relación . Este quiero cargar la dirección tablas t_customer y t_adress tiene muchas propiedades de la casa quot;homeAddressquot; ( ver tabla 7 ) incluyendo un cascade tan pronto como el objeto usado para quot;cascadingquot; de Customer es cargado. cualquier tipo de acción. En este ejemplo , quiero La anotación @JoinColumn quot;cascadequot; la acción de per- tiene los mismos atributos sistir y remover. De esta como @Column , excepto forma , cuando hago remo- que es usado para asociar ve o persist de un objeto atributos , En este ejemplo , customer este automática- Yo renombro la llave forá- mente lleva acabo esta ac- nea en un address_fk y no ción para el quot;addressquot; . El permito ningún valor null atributo fetch dice a JPA ( nullable=false) que política usar cuando cargamos una relación. Esta puede ser una asocia- JPA entonces creara los El atributo ción de carga tardía ( lazy siguientes DDLs con una fetch dice a JPA @Entity que política usar @Table(name = quot;t_customerquot;) public class Customer { cuando @Id cargamos una @GeneratedValue private Long id; (...) relación @Transient private Integer age; @OneToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) @JoinColumn(name = quot;address_fkquot;, nullable = false) private Address homeAddress; // constuctors, getters, setters }
  • 14.
  • 15. JAVA PERSISTENCE API Page 8 Querying Objects mite hacer querys comple- de operadores para filtrar la Hasta ahora yo estoy usan- jos sobre objetos ( asocia- data ( IN , NOT IN , EXIST , LIKE , IS do JPA para mapear mis ciones , herencia , clases NULL , IS NOT NULL ) o para con- objetos a una base de datos abstractas ) trolar las colecciones ( IS relacional y usar el entity EMPTY , IS NOT EMPTY , MEMBER manager para hacer algunas Los querys usan las pala- OF ) , También hay funcio- operaciones CRUD (Create, bras SELECT , FROM y nes para manejar Strings ( LOWER , UPPER , TRIM , CONCAT , read, update and delete ) , WHERE , mas un conjunto LENGTH , SUBS- Pero JPA también TRING ) , nú- permite que hagas // Finds the customers who are called John meros ( ABS , querys sobre los SQRT , MOD ) , o objetos. Esto usa Query query = em.createQuery(quot;SELECT c colecciones quot;Java Persistence FROM Customer c WHERE ( COUNT , MIN , Query Langua- c.firstname='John'quot;); MAX , SUM ). Co- gequot; ( JPQL) , el List<Customer> customers = que- mo SQL , tu cual es similar a ry.getResultList(); también pue- SQL y es también des ordenar Usted tiene que independiente de // Same query but using a parameter los resultados la base de datos , //Query query = em.createQuery(quot;SELECT c FROM ( ORDER BY) o hacer querys no Este es un lenguaje //Customer c WHERE c.firstname=:paramquot;); agruparlos //query.setParameter(quot;:paramquot;, quot;Johnquot;); (GROUP BY) rico que nos per- sobre una tabla, mas bien sobre Querying Objects, sobre objetos ... un objeto. Para hacer querys sobre los dos formas . De cualquiera objetos se necesita Entity- de las dos formas el string Manager para crear un ob- quot;Johnquot; es buscado : puede jeto Query . Luego tengo el ser parte del query JPQL o resultado del query llaman- puede ser pasado como do el getResultList o gen- parámetro , en este ultimo SingleResult cuando hay caso necesito usar el méto- solo un objeto retornado . do setParameter. En el ejemplo que sigue , quiero buscar todos los “Customers” quienes tienen el primer nombre quot;Johnquot; , Yo puedo hacer esto de JPQL Queries, ejemplos ... objeto “customer” y el to address. SELECT c FROM Como usted puede ver en Customer c WHERE este query JPQL usa la no- “c.firstname” es la primera c.homeAddress.country='US'; tación objeto . Usted tiene propiedad del objeto que hacer query no sobre “customer” . Si ustedes Acá hay un conjunto de una tabla, mas bien sobre quieren buscar todos los querys que nosotros pode- un objeto. El carácter “customers” que viven en mos hacer con JPQL . Ver “c” ( el nombre es irrele- U.S. , ustedes pueden usar tabla 8 vante ) es el alias de un esta notación , para obtener al atributo country del obje-