Introducción a Java Persistence API

Embed Size (px)

DESCRIPTION

Introducción al trabajo con Java Persistence Api (JPA), conceptos básicos y ejemplo aplicado a una tabla posts con los siguientes campos: post_id, post_title, post_date, post_body utilizando netbeans

Citation preview

  • 1. Lo hemos logrado. Qu sigue? Ya hemos desarrollado una aplicacin web con JAVA EE, utilizando Derby como base de datos, esta misma aplicacin puede desarrollarse de diferentes maneras, las cuales no slo resultan ms eficientes sino ms seguras

2. Alternativas

  • Java Persistence

3. Java Server Faces CRUD 4. Spring MVC 2.5 5. Java Persistence

  • La API de Java Persistence (JPA) es un framework para el trabajo con bases de datos relacionales, compuesta por tres partes:
  • El paquete: javax.persistence

6. El lenguaje de consultas de Persistence 7. Los metadatos para los objetos y sus relaciones 8. Java Persistence: Definiciones

  • Una entidad en JPA se refiere generalmente a una tabla de la base de datos

9. Las instancias de una entidad corresponden a filas dentro de la tabla 10. Generalmente las entidades se relacionan con otras entidades, estas relaciones se expresan mediante los metadatos 11. Los metadatos de las relaciones que se dan entre los objetos se pueden definir en un archivo XML o empleando anotaciones en el archivo de cada clase 12. Java Persistence: Definiciones

  • El lenguaje de consultas JPQL recuerda en su forma al SQL estndar, pero en lugar de operar sobre tablas de la base de datos lo hace sobre entidades

13. POJO : Plain Old Java Object -> clases que no extienden a ninguna otra: MyDb.javaesPOJO, NewPostServletno esPOJO 14. Qu es Persistencia?

  • Por persistencia se entiende almacenar los datos de una aplicacin en un medio fsico como una base de datos, un archivo de texto, etc...

15. Posts: tabla -> entidad

  • La tabla Posts que empleamos en el ejemplo anterior ser ahora una entidad.

16. Ahora que es una entidad cuenta con tres caractersticas:

  • Persistencia: los datos pueden almacenarse y recuperarse de una base de datos

17. Identidad: cada instancia de la entidad es nica 18. Soporte Transaccional: las operaciones CRUD (CReate, Update, Delete ) para esta entidad se realizan de forma transaccional 19. Antes de comenzar a #programar public class post{

  • private int post_id;

20. private String post_title; 21. private Date post_date; 22. private String post_body; 23. //getter & setter methods } 24. Antes de comenzar a #programar

  • Por getter & setter methods nos referimos ac a los mtodos que sirven para fijar y recuperar valores, continuando con el mismo ejemplo anterior podramos pensar por ejemplo en los siguientes:
  • get_id

25. set_id 26. get_title 27. set_title 28. Anotaciones (@)

  • El siguiente cambio en el pseudocdigo convierte a esta clase POJO en una entidad:
    • @Entity
  • 29. public class posts{
  • private int post_id;

30. private String post_title; 31. ... 32. Identidad

  • Ahora debemos incluir una nueva anotacin que permita definir el campo que identificar cada instancia de la entidad que estamos definiendo:

@Entity public class posts{ @Id private int post_id; private String post_title; private Date post_date; private String post_body; //getter and setter methods } 33. Convenciones

  • Nombre de la tabla: MITABLA

34. Nombre de la clase: MiTabla 35. Nombre de las columnas: ATTR1, ATTR2, ATTR3 36. Nombre de los atributos: attr1, attr2, attr3 37. @ Generando id's automticamente

  • Si queremos que los id's de nuestra entidad se generen de forma automtica podemos incluir otra anotacin:

... @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private int post_id; ... 38. EntityManager

  • La clase en pseudo-cdigo es casi una entidad. Para que sea completamente una entidad es necesario asociarla con un EntityManager

39. EntityManager: se refiere a una API que ofrece los servicios requeridos para trabajar con una entidad 40. En J2SE se define un EntityManager de la siguiente manera (explcita): EntityManagerFactory entityManagerFactory =Persistence.createEntityManagerFactory(PersistentUnitName); EntityManager eManager = entityManagerFactory.createEntityManager(); 41. EntityManager

  • En J2EE se emplea una anotacin en la clase de la entidad que se desea manejar y el contenedor (Servidor de Aplicaciones) se encarga del resto:

@Resource private EntityManager entityManager; 42. Persistence Context

  • Un contexto de persistencia administra un conjunto de entidades que a su vez es manejado por un EntityManager. El contexto de persistencia lleva el registro del estado y/o los cambios que puedan ocurrirle a una entidad. El EntityManager por su parte hace uso de los servicios que provee el contexto de persistencia para enviar (commit) o deshacer estos cambios. Tan pronto como se crea un objeto EntityManager ste es asociado implcitamente con el contexto de persistencia correspondiente.

43. Entidades y Transacciones

  • Todas las entidades cuentan con la propiedad de ser transaccionales. Todas sus operaciones CRUD se realizan en un contexto transaccional. Existen dos clases principales de transacciones: JTA y Resource-local

44. Con las transacciones JTA el programador no debe preocuparse por nada, pero en las transacciones tipo Resource-local las validaciones corren por su cuenta y basado en los resultados de las mismas debe determinar si enva una transaccin (commit) o por el contrario la anula (roll-back) 45. Operaciones sobre Entidades

  • Persistencia:
  • postEntity postObject = new postEntity();

46. postObject.set();//definir valores para el objeto 47. entityManager.persist(postObject); 48. Operaciones sobre Entidades II

  • Consultas: el programador est en libertad de usar objetos EntityManager para consultas simples u objetos Query para consultas ms complejas

49. find() es un mtodo propio de la clase EntityManager y permite recuperar una instancia de una entidad empleando el nombre de la clase y la llave primaria: postEntity elPost =entityManager.find(postEntity.class, 1); If (elPost != null){ // post object puede o no ser null. // Procesar el objecto } 50. Operaciones sobre Entidades III

  • delete() es el mtodo de la clase EntityManager que permite eliminar una instancia de una entidad:

postEntity elPost = entityManager.find(postEntity.class, 1); if (elPost != null){ // post object puede o no ser null. // eliminar el objecto EntityManager.remove(elPost); } 51. Operaciones sobre Entidades IV

  • update() es el mtodo de la clase EntityManager que permite actualizar una instancia de una entidad:

postEntity elPost = entityManager.find(postEntity.class, 1); If (elPost != null){ // post object puede o no ser null. // modificar los atributos del objecto con los metodos set elPost.setTitle("Un nuevo titulo"); EntityManager.merge(elPost); } 52. Operaciones sobre Entidades V

  • flush() es el mtodo que sincroniza los cambios realizados sobre una entidad con la base de datos:

postEntity elPost = entityManager.find(postEntity.class, 1); If (elPost != null){ // post object puede o no ser null. // modificar los atributos del objecto con los metodos set elPost.setTitle("Un nuevo titulo"); EntityManager.merge(elPost); EntityManager.flush(); } 53. Operaciones sobre Entidades VI

  • refresh() es el mtodo que devuelve los atributos de un objeto al ltimo estado recuperado desde la base de datos:

postEntity elPost = entityManager.find(postEntity.class, 1); If (elPost != null){ // post object puede o no ser null. // modificar los atributos del objecto con los metodos set elPost.setTitle("Un nuevo titulo"); EntityManager.merge(elPost); EntityManager.refresh(); } 54. find() no es muy flexible

  • Es claro que contar con la posibilidad de recuperar instancias de una entidad, exclusivamente utilizando su llave primaria, no es adecuado en prcticamente ningn ambiente. Para superar este obstculo es necesario emplear JPQL, un lenguaje de consultados basado en SQL y orientado a objetos

55. Existen 2 tipos de consultas diferentes: estticas y dinmicas 56. Static Query

  • Una consulta esttica se define empleando XML justo antes de la definicin de la clase de la entidad. Este tipo de consultas llevan un nombre gracias al cual otros componentes de la misma unidad de persistencia pueden usarla:

@NamedQuery(name = PostEntity.findAll query = SELECT M FROM POSTENTITY) @Entity class PostEntity{ } 57. Static Query II

  • Luego de definida, una consulta esttica puede utilizarse de la siguiente manera:

Query findAllQuery = entityManager. createNamedQuery(PostEntity.findAll) ; 58. Static Query III

  • Tambin es posible definir arreglos de consultas estticas para usarlos luego:

@NamedQueries( {@NamedQuery(name = Post.selectAllQuery query = SELECT M FROM POSTENTITY),@NamedQuery(name = Post.deleteAllQuery query = DELETE M FROM POSTENTITY)} ) 59. Dynamic Query

  • Una consulta dinmica se define dentro del cdigo de la entidad, empleando cdigo SQL corriente. Aunque a primera vista puede resultar ms simple que definir consultas estticas, su uso puede disminuir en gran medida el desempeo de la aplicacin ya que todo el mapeo de objetos / base de datos ocurre en tiempo de ejecucin:

Query singleSelectQuery = entityManager.createQuery( SELECT M FROM MOBILEENTITY WHERE M.IMEI = ABC-123); 60. Trabajando con los resultados

  • Una consulta puede traer un resultado, en cuyo caso se accede a el de la siguiente manera:
  • PostEntity postObj = singleSelectQuery. getSingleResult() ;
  • O puede traer mltiples resultados en cuyo caso es necesario convertir (cast) el resultado a un objeto tipo Lista:
  • List posts = (List)multipleSelect. getResultList() ;

61. Parmetros para las Consultas

  • Tanto las consultas dinmicas como las consultas estticas pueden emplear parmetros dinmicos, los cuales son enviados en tiempo de ejecucin:
  • @NamedQuery(

62. name = Post.findByTitle 63. query = SELECT P FROM POSTENTITY WHERE P.TITLELIKE '% :keyword %' 64. )

  • Y luego en el cdigo podra llamarse pasando el parmetro deseado:
  • Query namedQuery = entityManager.createNamedQuery(Post.findByTitle);

65. namedQuery.setParameter(keyword, entradaUsuario); 66. Paginacin de Resultados

  • Si una consulta devuelve, por ejemplo, 1000 resultados. No es una buena idea devolver todo el conjunto de resultados al usuario de una sola vez, en lugar de esto deben dividirse los resultados en pginas de menor tamao e ir retornando una pgina a la vez de acuerdo con las solicitudes del usuario

67. Paginacin de Resultados int maxRecords = 10;int startPosition = 0;String queryString = SELECT M FROM MOBILEENTITY;while( true ){Query selectQuery = entityManager.createQuery(queryString);selectQuery.setMaxResults(maxRecords);selectQuery.setFirstResult(startPosition);List mobiles = entityManager.getResultList(queryString);if (mobiles.isEmpty()){break;}//Process the mobile entities.process(mobiles);entityManager.clear(); startPosition = startPosition + mobiles.size(); } 68. Unidades de Persistencia

  • Unidad de Persistencia: una manera de categorizar un conjunto de entidades que trabajaran de forma conjunta y compartirn una misma configuracin

69. Las unidades de persistencia se definen empleando archivos XML y deben asociarse a los objetos EntityManager:

  • @PersistentUnit(unitName = MyPostPersistentUnit)

70. private EntityManager entityManager; 71. Ejemplo: utilizando JPA para Blog

  • Paso 1: crear una unidad de persistencia:
  • Proveedor EclipseLink

72. DataSource: conexin con la base de datos del blog (si no existe crear) Paso 2: crear una clase para la entidad de la tabla (posts) 73. Paso 3: crear el Servlet para que el usuario pueda buscar 74. Paso 4: asociar el EntityManager al Servlet 75. Paso 5: definir el mtodo de bsqueda y la interfaz 76. Creacin Unidad Persistencia 77. Creacin Unidad Persistencia 78. Creacin Entidad 79. Creacin Entidad 80. Creacin Entidad 81. Creacin Servlet 82. Creacin Servlet 83. Creacin Servlet 84. Asociando el EntityManager 85. Mtodo de bsqueda para el Servlet

  • public Posts findPostById(Integer auxPostId) {

86. Posts auxPost = null; 87. try { 88. Context ctx = (Context) new InitialContext().lookup("java:comp/env"); 89. utx.begin(); 90. EntityManager em = (EntityManager) ctx.lookup("persistence/LogicalName"); 91. //em.persist(object); 92. auxPost = em.find(Posts.class, auxPostId); 93. utx.commit(); 94. } catch (Exception e) { 95. Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", e); 96. throw new RuntimeException(e); 97. } 98. return auxPost; 99. } 100. Interfaz de bsqueda Servlet

  • try {

101. // TODO output your page here 102. 103. out.println("Motor de Busqueda - Blog"); 104. String uiAuxId = request.getParameter("post_id"); 105. if (uiAuxId != null && !uiAuxId.isEmpty()) { 106. //resultados de la busqueda 107. Posts resultadoBusqueda = this.findPostById(Integer.parseInt(uiAuxId)); 108. if (resultadoBusqueda != null) { 109. out.println(""); 110. out.println(""); 111. out.println("Resultado de su bsqueda:"); 112. out.println("" + resultadoBusqueda.getPostTitle() + ""); 113. out.println(""); 114. out.println(""); 115. Interfaz de bsqueda Servlet

  • } else {

116. out.println(""); 117. out.println(""); 118. out.println("Su bsqueda no arrojo resultados"); 119. out.println(""); 120. out.println(""); 121. } 122. } else { 123. //formulario de busqueda 124. out.println(""); 125. out.println(""); 126. out.println(""); 127. out.println("Codigo del Post:"); 128. out.println(""); 129. out.println(""); 130. out.println(""); 131. out.println(""); 132. out.println(""); 133. out.println(""); 134. out.println(""); 135. } 136. Y si quisiramos aadir un post?

  • Paso 1: aadir un nuevo Servlet

137. Paso 2: definir la unidad de persistencia 138. Paso 3: implementar en l un mtodo que permita recuperar el ltimo id empleado 139. Paso 4: implementar la interfaz grfica 140. Mtodo para recuperar el ltimo id

  • protected Integer getLastId(){

141. Posts postAux = null; 142. try { 143. Context ctx = (Context) new InitialContext().lookup("java:comp/env"); 144. utx.begin(); 145. EntityManager em = (EntityManager) ctx.lookup("persistence/LogicalName"); 146. //em.persist(object); 147. Query findAllQuery = em.createNamedQuery("Posts.findAll"); 148. List posts = findAllQuery.getResultList(); 149. Mtodo para recuperar el ltimo id

  • //para recorrer una lista se requiere un iterador

150. Iterator auxiliar = posts.iterator(); 151. while(auxiliar.hasNext()){ 152. postAux = (Posts)auxiliar.next();//cast 153. } 154. utx.commit(); 155. } catch (Exception e) { 156. Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", e); 157. throw new RuntimeException(e); 158. } 159. return postAux.getPostId(); 160. } 161. Interfaz Servlet (antes de submit)

  • } else {

162. //formulario para la creacion de un nuevo post 163. out.println(""); 164. out.println(""); 165. out.println(""); 166. ... 167. out.println(""); 168. out.println(""); 169. out.println(""); 170. out.println(""); 171. out.println(""); 172. } 173. out.println("