SlideShare una empresa de Scribd logo
1 de 7
Descargar para leer sin conexión
JAVA DEVELOPER - INSTRUCTOR - LEONARDO TORRES ALTEZ


Advanced Mapping with JPA


Nuevos requerimientos de Watermelon ...
                           que tienen un “first




JPA
                           name”,un “last name” y     “delivery addreses” .
                           una “date of birth”, las   Cada uno de esos
                           “companies” tienen un      “addresses” puede ser
                           “name” un “contract        usado el fin de semana
                           name”, y un “number        o por las noches. Voy
                           of employees”. Esto me     a implementar esta
                           da la oportunidad de       información añadiendo
                           mapear una herencia        “tags” a un “address”.
Este articulo se va
                           con JPA                    Para hacer todo esto ,
construir sobre el ejem-
                           “Customers” tienen un      voy a usar relaciones
plo del primero : Una
                           “home address” pero        de tipo one-to-many y
libreta de direcciones
                           Watermelon también         many-to-many de JPA.
para una empresa ficti-
                           necesita definir un        La Figura muestra el
cia de música llamada
Watermelon. Para em-
pezar , vamos a imagi-
nar que Watermelon
tiene algunos nuevos
requerimientos , ahora
hay dos tipos de
“customers”:
“individuals” y
“companies”.
“individuals” son un
tipo de “customers”




Herencia con JPA ?
                                                      había sido manejada
Como dije Waterme-         también maneja una la
                                                      en los EJBs de persis-
lon ahora tiene dos        relación a el Address.
                                                      tencia , Gracias a JPA ,
tipos de “customers” :     Ambos Individual and
                                                      polimorfismo y heren-
“individuals” y            Company añaden atri-
                                                      cia son posibles ahora
“companies”. En el         butos específicos
                                                      en una aplicación Java
modelo puedo descri-       ( también un método
                                                      EE y Java SE. Contraria-
bir esto usando una        para calcular la edad
                                                      mente a las asociacio-
clase abstracta Custo-     del “individual” ).
                                                      nes donde solo hay
mer de la cual van a
                           La herencia es una no-     una forma de hacerlas ,
heredar las clases
                                                      con la herencia el des-
“Individual” y             ción de los lenguajes
                                                      arrollador tiene que
“Company”.                 orientados a objetos en
                                                      escoger entre diferen-
“Customer” tiene un        general y a Java en
                                                      tes estrategias:
ID , un “telephone         particular . Pero guar-
number” , un “email        dar esta relación jerár-
                                                      •
address” , y un método     quica en una estructura          Una simple tabla por clase
para validar “telephone    relacional (base de              heredada (SINGLE TABLE)
                                                            es la estrategia por defecto,
numbers” ( ver Anota-      datos )es complicado .           Esto significa que las tres
                                                            clases Customer , Individual
ciones Callback) , Esto    Hasta ahora la herencia          y Company usan una sola
                                                            tabla ( ejemplo
ADVANCED MAPPING WITH JPA                                                                                       Page 2




                                    Lo mínimo necesario ...
                                                                                        primary key. Esta opción provee
                                             Todos los atributos de estas tres          soporte para relaciones polimórfi-
                                             clases son mapeados a una sola             cas y esta es la opción que yo voy
                                             tabla. Esta forma es la mejor en           a usar para mapear la herencia para
                                             términos de performance ,desde             el sistema address book de Water-
                                             que una sola tabla es involucra-           melon.
                                             da. De esta forma no se puede
                                             restringir que algunos atributos
                                             sean no nulos ( porque todas las
                                                                                 Al escoger la estrategia de
                                             subclases son mapeadas en la
                                                                                 mapeo, esta tiene que ser
                                             misma tabla )
                                                                                 echa una sola vez en la
                                    •      Una tabla por entity class ( TA-
                                                                                 entidad raíz (clase Custo-
                                           BLE_PER_CLASS) . Todas las
                                                                                 mer), usando la anotación
                                           propiedades de una clase concreta,
                                           incluyendo propiedades que se
                                                                                 @javax.persistence.Inheritan
                                           heredan son mapeadas a columnas
                                           de una tabla . En mi ejemplo yo
                                                                                 ce . Esto es especificado en
                                           solo tengo una tabla t_company y
                                                                                 la clase Customer como
                                           una t_individual . Los atributos de
                                           la clase base abstracta Customer
                                                                                 sigue
                                           serán copiados en estas dos tablas.
                                    •                                            <—
                                           Una tabla por clase (JOINED). En
                                           esta estrategia la clase raíz de la
                                           jerarquía (Customer) tanto como
                                           cada subclase es representada en
                                           una tabla separada . En el ejemplo
                                           de Watermelon tendré una tabla
                                           base común t_customer con un ID ,
                                           telephone number , y un email
                                           adress. Las tablas de subclases
                                           ( t_company , t_individual ) serán
                                           unidas con la principal mediante su




                                                  Estrategia JOINED ...
@Entity
@Table(name = quot;t_customerquot;)
@Inheritance(strategy = InheritanceTy-
                                                  Para trabajar , la             para identificar que instancia               decido nombrar la columna
pe.JOINED)
                                                  estrategia JOI-                de la clase concreta es guarda-              discriminadora DISC, y darle
@DiscriminatorColumn(name = quot;DISCquot;, discri-
minatorType = DiscriminatorType.STRING,
                                                  NED ( también la               da ( es un individual o un                   una longitud de 5 . Yo puedo
length = 5)
                                                  SINGLE TA-                     company que es guardado en                   hacer esto usando la anota-
public abstract class Customer {
                                                  BLE) necesita                  la tabla t_customer? ). Sin                  ción
    @Id                                           información adi-               ninguna anotación la codifica-               @javax.persistence.Dicrimina
    @GeneratedValue
                                                  cional : una co-               ción por defecto va a crear                  torColumn . El contenido de
    private Long id;
                                                  lumna discrimida-              una columna llamada DTYPE                    esta columna puede ser custo-
    @Column(length = 15)
                                                  dora . Esta colum-             varchar(31) el cual su valor es              mizada en cada clase concreta
    protected String telephone;
    @Column(name = quot;e_mailquot;)                      na , situada en la             por defecto el nombre de la                  usando la anotación
    protected String email;
                                                  tabla principal ,              clase concreta ( no abstracta )              @DicrimitarorValue. El valor
    // constructors, getters, setters
                                                  habilita al persis-                                                         tiene que ser único y sirve
}
                                                  tence provider                 En el siguiente código , Yo                  para identificar una clase con-

                                    Estrategia JOINED ...
                                    creta . La codifi-
                                    cación por defec-
                                    to lo hará por
                                    defecto al nom-
                                    bre de la clase,
                                    Pero he decidido
                                    cambiar esto a
                                    “indiv” y
                                    “comp” . Ver
                                    tabla 1 .
JAVA PERSISTENCE API
Page 3



Unidad de Persistencia

Vea que cada una de las tres
entidades es mapeada a su
propia tabla ( usando la anota-
ción @Table ) .Como expli-
que en el articulo previo , el
EntityManager y las propieda-
des seteadas en la unidad de
persistencia automáticamente
creara estas tablas. El resulta-
do esta estrategia JOINED
son los DDLs y los contraints
de integridad entre las tres
tablas, como se muestra en la
Tabla 2. —>




Métodos CRUD...
Una vez que has escogido la        datos.
estrategia para mapear la
herencia , tu puedes hacer los        public void createCustomers() {
                                        // Gets an entity manager
métodos CRUD de cualquiera
                                        EntityManagerFactory emf = Persistence.createEntityManagerFactory
estas clases concretas usando         (quot;watermelonPUquot;);
el EntityManager tal como               EntityManager em = emf.createEntityManager();
entidad . En el siguiente códi-         EntityTransaction trans = em.getTransaction();
go yo creo una instancia de
                                        // Instantiates a company object
Company y una clase Indivi-             Company company = new Company(quot;Universalquot;, quot;Mr Universequot;, 50000,
dual que persisto en la base de       quot;+15488454quot;, quot;info@universal.comquot;);
                                        company.setHomeAddress(new Address(quot;World Streetquot;, quot;New Yorkquot;, quot;7448quot;,
                                      quot;UKquot;));

                                        // Instantiates an individual object
                                        calendar.set(1940, 10, 9);
                                        Individual individual = new Individual(quot;Johnquot;, quot;Lennonquot;, quot;+441909quot;,
                                      quot;john@lenon.comquot;, calendar.getTime());
                                        individual.setHomeAddress(new Address(quot;Abbey Roadquot;, quot;Londonquot;, quot;SW14quot;,
                                      quot;UKquot;));

                                          // Persists both customers
                                          trans.begin();
                                          em.persist(company);
                                          em.persist(individual);
                                          trans.commit();

                                          // Closes the entity manager and the factory
                                          em.close();
                                          emf.close();
                                      }
ADVANCED MAPPING WITH JPA                                                                   Page 4




Hacer queries sobre un modelo jerárquico también es posible con JPQL . Yo puedo hacer queries
en las clases concretas tanto como en la clase principal abstracta




Y yo puedo usar los atributos de la clase principal en los queries. Por ejemplo, el mail address
esta definido en la clase Customer , puedo usar este atributo en los queries envolviendo la clase
customer también en la clase Individual y Company




De acuerdo : no puedo usar los atributos de la clase hija para hacer queries en la clase padre.Por
ejemplo , el atributo first name es justo definido en Individual . Yo no puedo usar este para hacer
queries de customers y companies.




En el adress book , las companies tienen un numero de employees . JPQL tiene un set de funcio-
nes aritméticas que tu puede usar en un query.




Yo también puedo usar restricciones en estos números aplicando funciones : menor que , mayor
que , igual a . También obtener un rango de empleados
Page 5



One to Many ...
Ahora que ya esta mapeada la herencia. Voy a fijarme en el delivery addresses. En la Figura 1 una clase “Customer” tiene
un “home address” ( mapeado en el articulo previo ) y cero o muchos delivery addresses. Esto es representado por una
relación unidireccional , “one-to-many” entre “Customer” y “Address”.

Hay dos diferentes estrategias que tu puedes usar para tener una relación “one-to-many” en una base de datos relacional .
Lo primero es colocar un foreing key en la tabla representando “many” ( t_address) , apuntando a el primary key de la
tabla representando el “one” ( t_customer ) . Lo segundo es usar una tercera tabla ( join_table ) para servir como un link
entre estas dos, usando esta estrategia las relaciones “one-to-many” en JPA usan una tabla join. ( una tercera tabla )

El siguiente código muestra como manejar una relaciones de uno a muchos. Otra vez puedo dejar la codificación por de-
fecto y a JPA mapear la relación por mi , pero decido usar anotaciones para customizar el mapeo.

              @Entity
              @Table(name = quot;t_customerquot;)
              @Inheritance(strategy = InheritanceType.JOINED)
              @DiscriminatorColumn(name = quot;DISCquot;, discriminatorType = DiscriminatorTy-
              pe.STRING, length = 5)
              public abstract class Customer {
                @Id
                @GeneratedValue
                private Long id;
                @Column(length = 15)
                protected String telephone;
                @Column(name = quot;e_mailquot;)
                protected String email;
                @OneToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, Cas-
              cadeType.REMOVE})
                @JoinColumn(name = quot;home_address_fkquot;, nullable = false)
                private Address homeAddress;

                  @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
                  @JoinTable(name = quot;t_delivery_addressesquot;,
                    joinColumns = {@JoinColumn(name = quot;customer_fkquot;)},
                    inverseJoinColumns = {@JoinColumn(name = quot;address_fkquot;)})
                  private List deliveryAddresses = new ArrayList();

                  public void addDeliveryAddress(Address deliveryAddress) {
                    deliveryAddresses.add(deliveryAddress);
                  }

                  // constructors, getters, setters
              }

La anotación @javax.persistence.OneToMany es usada para relaciones “one-to-many” tiene los mismos atributos como
@OneToOne ( ver el articulo previo) .Lo que yo estoy haciendo en el código que sigue es notificar a JPA el “lazy load” de
el atributo “delivery address” ( atributo “fetch” ) y “cascade all ” de todos los eventos ( persist , remove , ..etc ) . Como
mencione JPA mapea una relación “one-to-many” usando una join table. Para customizar el nombre y columnas de esta
join table , Yo puedo usar la anotación @javax.persistence.JoinTable . De acuerdo a el código , la tabla join se llamara
(t_delivery_address ) . Para
cambiar los nombres de los
foreing key , yo tengo que
usar la anotación
@JoinColumn.
Con todas estas anotacio-
nes , JPA va a crear y ade-
cuar las tablas y los integrity
constraints. La tabla 3 mues-
tra los DDLs de las tres ta-
blas involucradas en la rela-
ción.
ADVANCED MAPPING WITH JPA                                                                  Page 6




Many to Many ...
                                   many” . En la base de datos ,
Para ayudar a clasificar los       esta información será guarda-
diferentes “addresses” que un      da exactamente de la misma
“customer” puede tener Wa-         forma que las relaciones
termelon quiere clasificarlos      “one-to-many” : usando una
( tag ) . Un tag es una etiqueta   tercera tabla que une los pri-
( un String) que puede ser         mary keys. En la Tabla 4 tu
añadido a una colección de         encontraras la anotación
addresses. “Tag” y “Address”       @ManyToMany usada en
tienen una relación bi–            conjunción con @JoinTable y
direccional , “many-to-            @JoinColumn.




   El identificador ( @id ) de la clase “Tag” es un atributo de tipo String. El valor es seteado
   manualmente, por eso es que no hay una anotación @GeneratedValue. Ambas clases
   usan la anotación @ManyToMany significa que la relación es bidireccional . Cualquiera
   de estas clases podría definir los atributos de la tabla join ( @JoinTable) pero he decidido
   que la clase Address lo haga. La tabla join entre los “addresses” y “tags” es llamada
   t_address_tag .

   @OneToMany y @ManyToMany lidian con colecciones de objetos. Para hacer querys
   sobre colecciones , JPQL tiene un conjunto de keywords como EMPTY , que verifica si
   una colección esta vacía o no , o MEMBER OF que verifica si un objeto es un miembro
   de la colección . El código siguiente nos muestra como un objeto “address” y sus “tags”
   están relacionados. Tanto como definir algunos querys.
JAVA PERSISTENCE API
Page 7




One to One Relationship
   Tag tag1 = new Tag(quot;24/7quot;);
   Tag tag2 = new Tag(quot;working hoursquot;);
   Tag tag3 = new Tag(quot;week-endsquot;);

   Address address = new Address(quot;Central Side Parkquot;, quot;New Yorkquot;, quot;7845quot;, quot;USquot;);
   address.addTag(tag1);
   address.addTag(tag2);
   address.addTag(tag3);

   // Perists the address and its tags
   trans.begin();
   em.persist(address);
   trans.commit();

   Query query;
   List<Address> addresses;

   // Finds all the addresses either in London or New York
   query = em.createQuery(quot;SELECT a FROM Address a WHERE a.city IN ('London', 'New York') quot;);
   addresses = query.getResultList();

   // Finds all the addresses that do not have a tag
   query = em.createQuery(quot;SELECT a FROM Address a WHERE a.tags IS EMPTYquot;);
   addresses = query.getResultList();

   // Finds all the addresses that have at least one tag
   query = em.createQuery(quot;SELECT a FROM Address a WHERE a.tags IS NOT EMPTYquot;);
   addresses = query.getResultList();

   // Finds all the addresses that have a quot;week-endsquot; tag
   query = em.createQuery(quot;SELECT a FROM Address a WHERE :param MEMBER OF a.tagsquot;);
   query.setParameter(quot;paramquot;, new Tag(quot;week-endsquot;));
   addresses = query.getResultList();

Más contenido relacionado

Destacado

How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 

Destacado (20)

How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
 
12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work
 
ChatGPT webinar slides
ChatGPT webinar slidesChatGPT webinar slides
ChatGPT webinar slides
 

Jpa Parte 2 Leonardo Torres Altez

  • 1. JAVA DEVELOPER - INSTRUCTOR - LEONARDO TORRES ALTEZ Advanced Mapping with JPA Nuevos requerimientos de Watermelon ... que tienen un “first JPA name”,un “last name” y “delivery addreses” . una “date of birth”, las Cada uno de esos “companies” tienen un “addresses” puede ser “name” un “contract usado el fin de semana name”, y un “number o por las noches. Voy of employees”. Esto me a implementar esta da la oportunidad de información añadiendo mapear una herencia “tags” a un “address”. Este articulo se va con JPA Para hacer todo esto , construir sobre el ejem- “Customers” tienen un voy a usar relaciones plo del primero : Una “home address” pero de tipo one-to-many y libreta de direcciones Watermelon también many-to-many de JPA. para una empresa ficti- necesita definir un La Figura muestra el cia de música llamada Watermelon. Para em- pezar , vamos a imagi- nar que Watermelon tiene algunos nuevos requerimientos , ahora hay dos tipos de “customers”: “individuals” y “companies”. “individuals” son un tipo de “customers” Herencia con JPA ? había sido manejada Como dije Waterme- también maneja una la en los EJBs de persis- lon ahora tiene dos relación a el Address. tencia , Gracias a JPA , tipos de “customers” : Ambos Individual and polimorfismo y heren- “individuals” y Company añaden atri- cia son posibles ahora “companies”. En el butos específicos en una aplicación Java modelo puedo descri- ( también un método EE y Java SE. Contraria- bir esto usando una para calcular la edad mente a las asociacio- clase abstracta Custo- del “individual” ). nes donde solo hay mer de la cual van a La herencia es una no- una forma de hacerlas , heredar las clases con la herencia el des- “Individual” y ción de los lenguajes arrollador tiene que “Company”. orientados a objetos en escoger entre diferen- “Customer” tiene un general y a Java en tes estrategias: ID , un “telephone particular . Pero guar- number” , un “email dar esta relación jerár- • address” , y un método quica en una estructura Una simple tabla por clase para validar “telephone relacional (base de heredada (SINGLE TABLE) es la estrategia por defecto, numbers” ( ver Anota- datos )es complicado . Esto significa que las tres clases Customer , Individual ciones Callback) , Esto Hasta ahora la herencia y Company usan una sola tabla ( ejemplo
  • 2. ADVANCED MAPPING WITH JPA Page 2 Lo mínimo necesario ... primary key. Esta opción provee Todos los atributos de estas tres soporte para relaciones polimórfi- clases son mapeados a una sola cas y esta es la opción que yo voy tabla. Esta forma es la mejor en a usar para mapear la herencia para términos de performance ,desde el sistema address book de Water- que una sola tabla es involucra- melon. da. De esta forma no se puede restringir que algunos atributos sean no nulos ( porque todas las Al escoger la estrategia de subclases son mapeadas en la mapeo, esta tiene que ser misma tabla ) echa una sola vez en la • Una tabla por entity class ( TA- entidad raíz (clase Custo- BLE_PER_CLASS) . Todas las mer), usando la anotación propiedades de una clase concreta, incluyendo propiedades que se @javax.persistence.Inheritan heredan son mapeadas a columnas de una tabla . En mi ejemplo yo ce . Esto es especificado en solo tengo una tabla t_company y la clase Customer como una t_individual . Los atributos de la clase base abstracta Customer sigue serán copiados en estas dos tablas. • <— Una tabla por clase (JOINED). En esta estrategia la clase raíz de la jerarquía (Customer) tanto como cada subclase es representada en una tabla separada . En el ejemplo de Watermelon tendré una tabla base común t_customer con un ID , telephone number , y un email adress. Las tablas de subclases ( t_company , t_individual ) serán unidas con la principal mediante su Estrategia JOINED ... @Entity @Table(name = quot;t_customerquot;) @Inheritance(strategy = InheritanceTy- Para trabajar , la para identificar que instancia decido nombrar la columna pe.JOINED) estrategia JOI- de la clase concreta es guarda- discriminadora DISC, y darle @DiscriminatorColumn(name = quot;DISCquot;, discri- minatorType = DiscriminatorType.STRING, NED ( también la da ( es un individual o un una longitud de 5 . Yo puedo length = 5) SINGLE TA- company que es guardado en hacer esto usando la anota- public abstract class Customer { BLE) necesita la tabla t_customer? ). Sin ción @Id información adi- ninguna anotación la codifica- @javax.persistence.Dicrimina @GeneratedValue cional : una co- ción por defecto va a crear torColumn . El contenido de private Long id; lumna discrimida- una columna llamada DTYPE esta columna puede ser custo- @Column(length = 15) dora . Esta colum- varchar(31) el cual su valor es mizada en cada clase concreta protected String telephone; @Column(name = quot;e_mailquot;) na , situada en la por defecto el nombre de la usando la anotación protected String email; tabla principal , clase concreta ( no abstracta ) @DicrimitarorValue. El valor // constructors, getters, setters habilita al persis- tiene que ser único y sirve } tence provider En el siguiente código , Yo para identificar una clase con- Estrategia JOINED ... creta . La codifi- cación por defec- to lo hará por defecto al nom- bre de la clase, Pero he decidido cambiar esto a “indiv” y “comp” . Ver tabla 1 .
  • 3. JAVA PERSISTENCE API Page 3 Unidad de Persistencia Vea que cada una de las tres entidades es mapeada a su propia tabla ( usando la anota- ción @Table ) .Como expli- que en el articulo previo , el EntityManager y las propieda- des seteadas en la unidad de persistencia automáticamente creara estas tablas. El resulta- do esta estrategia JOINED son los DDLs y los contraints de integridad entre las tres tablas, como se muestra en la Tabla 2. —> Métodos CRUD... Una vez que has escogido la datos. estrategia para mapear la herencia , tu puedes hacer los public void createCustomers() { // Gets an entity manager métodos CRUD de cualquiera EntityManagerFactory emf = Persistence.createEntityManagerFactory estas clases concretas usando (quot;watermelonPUquot;); el EntityManager tal como EntityManager em = emf.createEntityManager(); entidad . En el siguiente códi- EntityTransaction trans = em.getTransaction(); go yo creo una instancia de // Instantiates a company object Company y una clase Indivi- Company company = new Company(quot;Universalquot;, quot;Mr Universequot;, 50000, dual que persisto en la base de quot;+15488454quot;, quot;info@universal.comquot;); company.setHomeAddress(new Address(quot;World Streetquot;, quot;New Yorkquot;, quot;7448quot;, quot;UKquot;)); // Instantiates an individual object calendar.set(1940, 10, 9); Individual individual = new Individual(quot;Johnquot;, quot;Lennonquot;, quot;+441909quot;, quot;john@lenon.comquot;, calendar.getTime()); individual.setHomeAddress(new Address(quot;Abbey Roadquot;, quot;Londonquot;, quot;SW14quot;, quot;UKquot;)); // Persists both customers trans.begin(); em.persist(company); em.persist(individual); trans.commit(); // Closes the entity manager and the factory em.close(); emf.close(); }
  • 4. ADVANCED MAPPING WITH JPA Page 4 Hacer queries sobre un modelo jerárquico también es posible con JPQL . Yo puedo hacer queries en las clases concretas tanto como en la clase principal abstracta Y yo puedo usar los atributos de la clase principal en los queries. Por ejemplo, el mail address esta definido en la clase Customer , puedo usar este atributo en los queries envolviendo la clase customer también en la clase Individual y Company De acuerdo : no puedo usar los atributos de la clase hija para hacer queries en la clase padre.Por ejemplo , el atributo first name es justo definido en Individual . Yo no puedo usar este para hacer queries de customers y companies. En el adress book , las companies tienen un numero de employees . JPQL tiene un set de funcio- nes aritméticas que tu puede usar en un query. Yo también puedo usar restricciones en estos números aplicando funciones : menor que , mayor que , igual a . También obtener un rango de empleados
  • 5. Page 5 One to Many ... Ahora que ya esta mapeada la herencia. Voy a fijarme en el delivery addresses. En la Figura 1 una clase “Customer” tiene un “home address” ( mapeado en el articulo previo ) y cero o muchos delivery addresses. Esto es representado por una relación unidireccional , “one-to-many” entre “Customer” y “Address”. Hay dos diferentes estrategias que tu puedes usar para tener una relación “one-to-many” en una base de datos relacional . Lo primero es colocar un foreing key en la tabla representando “many” ( t_address) , apuntando a el primary key de la tabla representando el “one” ( t_customer ) . Lo segundo es usar una tercera tabla ( join_table ) para servir como un link entre estas dos, usando esta estrategia las relaciones “one-to-many” en JPA usan una tabla join. ( una tercera tabla ) El siguiente código muestra como manejar una relaciones de uno a muchos. Otra vez puedo dejar la codificación por de- fecto y a JPA mapear la relación por mi , pero decido usar anotaciones para customizar el mapeo. @Entity @Table(name = quot;t_customerquot;) @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn(name = quot;DISCquot;, discriminatorType = DiscriminatorTy- pe.STRING, length = 5) public abstract class Customer { @Id @GeneratedValue private Long id; @Column(length = 15) protected String telephone; @Column(name = quot;e_mailquot;) protected String email; @OneToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, Cas- cadeType.REMOVE}) @JoinColumn(name = quot;home_address_fkquot;, nullable = false) private Address homeAddress; @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable(name = quot;t_delivery_addressesquot;, joinColumns = {@JoinColumn(name = quot;customer_fkquot;)}, inverseJoinColumns = {@JoinColumn(name = quot;address_fkquot;)}) private List deliveryAddresses = new ArrayList(); public void addDeliveryAddress(Address deliveryAddress) { deliveryAddresses.add(deliveryAddress); } // constructors, getters, setters } La anotación @javax.persistence.OneToMany es usada para relaciones “one-to-many” tiene los mismos atributos como @OneToOne ( ver el articulo previo) .Lo que yo estoy haciendo en el código que sigue es notificar a JPA el “lazy load” de el atributo “delivery address” ( atributo “fetch” ) y “cascade all ” de todos los eventos ( persist , remove , ..etc ) . Como mencione JPA mapea una relación “one-to-many” usando una join table. Para customizar el nombre y columnas de esta join table , Yo puedo usar la anotación @javax.persistence.JoinTable . De acuerdo a el código , la tabla join se llamara (t_delivery_address ) . Para cambiar los nombres de los foreing key , yo tengo que usar la anotación @JoinColumn. Con todas estas anotacio- nes , JPA va a crear y ade- cuar las tablas y los integrity constraints. La tabla 3 mues- tra los DDLs de las tres ta- blas involucradas en la rela- ción.
  • 6. ADVANCED MAPPING WITH JPA Page 6 Many to Many ... many” . En la base de datos , Para ayudar a clasificar los esta información será guarda- diferentes “addresses” que un da exactamente de la misma “customer” puede tener Wa- forma que las relaciones termelon quiere clasificarlos “one-to-many” : usando una ( tag ) . Un tag es una etiqueta tercera tabla que une los pri- ( un String) que puede ser mary keys. En la Tabla 4 tu añadido a una colección de encontraras la anotación addresses. “Tag” y “Address” @ManyToMany usada en tienen una relación bi– conjunción con @JoinTable y direccional , “many-to- @JoinColumn. El identificador ( @id ) de la clase “Tag” es un atributo de tipo String. El valor es seteado manualmente, por eso es que no hay una anotación @GeneratedValue. Ambas clases usan la anotación @ManyToMany significa que la relación es bidireccional . Cualquiera de estas clases podría definir los atributos de la tabla join ( @JoinTable) pero he decidido que la clase Address lo haga. La tabla join entre los “addresses” y “tags” es llamada t_address_tag . @OneToMany y @ManyToMany lidian con colecciones de objetos. Para hacer querys sobre colecciones , JPQL tiene un conjunto de keywords como EMPTY , que verifica si una colección esta vacía o no , o MEMBER OF que verifica si un objeto es un miembro de la colección . El código siguiente nos muestra como un objeto “address” y sus “tags” están relacionados. Tanto como definir algunos querys.
  • 7. JAVA PERSISTENCE API Page 7 One to One Relationship Tag tag1 = new Tag(quot;24/7quot;); Tag tag2 = new Tag(quot;working hoursquot;); Tag tag3 = new Tag(quot;week-endsquot;); Address address = new Address(quot;Central Side Parkquot;, quot;New Yorkquot;, quot;7845quot;, quot;USquot;); address.addTag(tag1); address.addTag(tag2); address.addTag(tag3); // Perists the address and its tags trans.begin(); em.persist(address); trans.commit(); Query query; List<Address> addresses; // Finds all the addresses either in London or New York query = em.createQuery(quot;SELECT a FROM Address a WHERE a.city IN ('London', 'New York') quot;); addresses = query.getResultList(); // Finds all the addresses that do not have a tag query = em.createQuery(quot;SELECT a FROM Address a WHERE a.tags IS EMPTYquot;); addresses = query.getResultList(); // Finds all the addresses that have at least one tag query = em.createQuery(quot;SELECT a FROM Address a WHERE a.tags IS NOT EMPTYquot;); addresses = query.getResultList(); // Finds all the addresses that have a quot;week-endsquot; tag query = em.createQuery(quot;SELECT a FROM Address a WHERE :param MEMBER OF a.tagsquot;); query.setParameter(quot;paramquot;, new Tag(quot;week-endsquot;)); addresses = query.getResultList();