Sei sulla pagina 1di 51

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

Alternativas

Java Persistence Java Server Faces CRUD Spring MVC 2.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 El lenguaje de consultas de Persistence Los metadatos para los objetos y sus relaciones

Java Persistence: Definiciones

Una entidad en JPA se refiere generalmente a una tabla de la base de datos Las instancias de una entidad corresponden a filas dentro de la tabla Generalmente las entidades se relacionan con otras entidades, estas relaciones se expresan mediante los metadatos 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

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 POJO: Plain Old Java Object clases que no extienden a ninguna otra: MyDb.java es POJO, NewPostServlet no es POJO

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...

Posts: tabla entidad

La tabla Posts que empleamos en el ejemplo anterior ser ahora una entidad. Ahora que es una entidad cuenta con tres caractersticas:

Persistencia: los datos pueden almacenarse y recuperarse de una base de datos Identidad: cada instancia de la entidad es nica Soporte Transaccional: las operaciones CRUD (CReate, Update, Delete ) para esta entidad se realizan de forma transaccional

Antes de comenzar a #programar


public class post{

private int post_id; private String post_title; private Date post_date; private String post_body; //getter & setter methods

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 set_id get_title set_title

Anotaciones (@)

El siguiente cambio en el pseudocdigo convierte a esta clase POJO en una entidad:


@Entity public class posts{


private int post_id; private String post_title; ...

Identidad

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

@Entity publicclassposts{ @Id privateintpost_id; privateStringpost_title; privateDatepost_date; privateStringpost_body; //getterandsettermethods }

Convenciones

Nombre de la tabla: MITABLA Nombre de la clase: MiTabla Nombre de las columnas: ATTR1, ATTR2, ATTR3 Nombre de los atributos: attr1, attr2, attr3

@ 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) privateintpost_id;

...

EntityManager

La clase en pseudo-cdigo es casi una entidad. Para que sea completamente una entidad es necesario asociarla con un EntityManager EntityManager: se refiere a una API que ofrece los servicios requeridos para trabajar con una entidad En J2SE se define un EntityManager de la siguiente manera (explcita):

EntityManagerFactoryentityManagerFactory= Persistence.createEntityManagerFactory(PersistentUnitNa me); EntityManagereManager= entityManagerFactory.createEntityManager();

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

privateEntityManagerentityManager;

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.

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 Resourcelocal 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)

Operaciones sobre Entidades

Persistencia:
postEntitypostObject=newpostEntity(); postObject.set();//definirvaloresparaelobjeto entityManager.persist(postObject);

Operaciones sobre Entidades II

Consultas: el programador est en libertad de usar objetos EntityManager para consultas simples u objetos Query para consultas ms complejas 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:

postEntityelPost=entityManager.find(postEntity.class,1); If(elPost!=null){//postobjectpuedeonosernull. //Procesarelobjecto }

Operaciones sobre Entidades III

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

postEntityelPost= entityManager.find(postEntity.class,1); if(elPost!=null){//postobjectpuedeono sernull. //eliminarelobjecto EntityManager.remove(elPost); }

Operaciones sobre Entidades IV

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

postEntityelPost= entityManager.find(postEntity.class,1); If(elPost!=null){//postobjectpuedeonoser null. //modificarlosatributosdelobjectoconlosmetodos set elPost.setTitle("Unnuevotitulo"); EntityManager.merge(elPost); }

Operaciones sobre Entidades V

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

postEntityelPost=entityManager.find(postEntity.class,1); If(elPost!=null){//postobjectpuedeonosernull. //modificarlosatributosdelobjectoconlosmetodosset elPost.setTitle("Unnuevotitulo"); EntityManager.merge(elPost); EntityManager.flush(); }

Operaciones sobre Entidades VI

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

postEntityelPost=entityManager.find(postEntity.class,1); If(elPost!=null){//postobjectpuedeonosernull. //modificarlosatributosdelobjectoconlosmetodosset elPost.setTitle("Unnuevotitulo"); EntityManager.merge(elPost); EntityManager.refresh(); }

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 Existen 2 tipos de consultas diferentes: estticas y dinmicas

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=SELECTMFROMPOSTENTITY) @Entity classPostEntity{ }

Static Query II

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

QueryfindAllQuery= entityManager.createNamedQuery(PostEntity. findAll);

Static Query III

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

@NamedQueries({ @NamedQuery(name=Post.selectAllQuery query=SELECTMFROMPOSTENTITY), @NamedQuery(name=Post.deleteAllQuery query=DELETEMFROMPOSTENTITY) })

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:

QuerysingleSelectQuery= entityManager.createQuery(SELECTMFROM MOBILEENTITYWHEREM.IMEI=ABC123);

Trabajando con los resultados

Una consulta puede traer un resultado, en cuyo caso se accede a el de la siguiente manera:
PostEntitypostObj= singleSelectQuery.getSingleResult();

O puede traer mltiples resultados en cuyo caso es necesario convertir (cast) el resultado a un objeto tipo Lista:
Listposts= (List)multipleSelect.getResultList();

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( name=Post.findByTitle query=SELECTPFROMPOSTENTITYWHEREP.TITLELIKE '%:keyword%' ) Y luego en el cdigo podra llamarse pasando el parmetro deseado: QuerynamedQuery= entityManager.createNamedQuery(Post.findByTitle); namedQuery.setParameter(keyword,entradaUsuario);

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

Paginacin de Resultados
intmaxRecords=10; intstartPosition=0; StringqueryString=SELECTMFROMMOBILEENTITY; while(true){ QueryselectQuery=entityManager.createQuery(queryString); selectQuery.setMaxResults(maxRecords); selectQuery.setFirstResult(startPosition); Listmobiles=entityManager.getResultList(queryString); if(mobiles.isEmpty()){ break; } //Processthemobileentities. process(mobiles); entityManager.clear(); startPosition=startPosition+mobiles.size(); }

Unidades de Persistencia

Unidad de Persistencia: una manera de categorizar un conjunto de entidades que trabajaran de forma conjunta y compartirn una misma configuracin Las unidades de persistencia se definen empleando archivos XML y deben asociarse a los objetos EntityManager: @PersistentUnit(unitName= MyPostPersistentUnit) privateEntityManagerentityManager;

Ejemplo: utilizando JPA para Blog

Paso 1: crear una unidad de persistencia:


Proveedor EclipseLink 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) Paso 3: crear el Servlet para que el usuario pueda buscar Paso 4: asociar el EntityManager al Servlet Paso 5: definir el mtodo de bsqueda y la interfaz

Creacin Unidad Persistencia

Creacin Unidad Persistencia

Creacin Entidad

Creacin Entidad

Creacin Entidad

Creacin Servlet

Creacin Servlet

Creacin Servlet

Asociando el EntityManager

Mtodo de bsqueda para el Servlet


publicPostsfindPostById(IntegerauxPostId){ PostsauxPost=null; try{ Contextctx=(Context)new InitialContext().lookup("java:comp/env"); utx.begin(); EntityManagerem=(EntityManager) ctx.lookup("persistence/LogicalName"); //em.persist(object); auxPost=em.find(Posts.class,auxPostId); utx.commit(); }catch(Exceptione){ Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exceptioncaught",e); thrownewRuntimeException(e); } returnauxPost; }

Interfaz de bsqueda Servlet

try { // TODO output your page here out.println("<h1>Motor de Busqueda - Blog</h1>"); String uiAuxId = request.getParameter("post_id"); if (uiAuxId != null && !uiAuxId.isEmpty()) { //resultados de la busqueda Posts resultadoBusqueda = this.findPostById(Integer.parseInt(uiAuxId)); if (resultadoBusqueda != null) { out.println("<table>"); out.println("<tr>"); out.println("<td>Resultado de su b&uacute;squeda:</td>"); out.println("<td>" + resultadoBusqueda.getPostTitle() + "</td>"); out.println("</tr>"); out.println("</table>");

Interfaz de bsqueda Servlet


} else { out.println("<table>"); out.println("<tr>"); out.println("<td>Su b&uacute;squeda no arrojo resultados</td>"); out.println("</tr>"); out.println("</table>"); } } else { //formulario de busqueda out.println("<form method='POST' action='./SearchPost'>"); out.println("<table>"); out.println("<tr>"); out.println("<td>Codigo del Post:</td>"); out.println("<td><input type='text' name='post_id'></td>"); out.println("</tr>"); out.println("<tr>"); out.println("<td colspan='2'><input type='submit' name='sendBtn' label='Search'></td>"); out.println("</tr>"); out.println("</table>"); out.println("</form>"); }

Y si quisiramos aadir un post?


Paso 1: aadir un nuevo Servlet Paso 2: definir la unidad de persistencia Paso 3: implementar en l un mtodo que permita recuperar el ltimo id empleado Paso 4: implementar la interfaz grfica

Mtodo para recuperar el ltimo id


protectedIntegergetLastId(){ PostspostAux=null; try{ Contextctx=(Context)new InitialContext().lookup("java:comp/env"); utx.begin(); EntityManagerem=(EntityManager) ctx.lookup("persistence/LogicalName"); //em.persist(object); QueryfindAllQuery= em.createNamedQuery("Posts.findAll"); Listposts= findAllQuery.getResultList();

Mtodo para recuperar el ltimo id

//para recorrer una lista se requiere un iterador Iterator auxiliar = posts.iterator(); while(auxiliar.hasNext()){ postAux = (Posts)auxiliar.next();//cast } utx.commit(); } catch (Exception e) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", e); throw new RuntimeException(e); } return postAux.getPostId(); }

Interfaz Servlet (antes de submit)

} else { //formulario para la creacion de un nuevo post out.println("<form method='POST' action='./NewPost'>"); out.println("<table>"); out.println("<tr>"); ... out.println("<tr>"); out.println("<td colspan='2'><input type='submit' name='btnSubmit' value='savePost' label='Save'></td>"); out.println("</tr>"); out.println("</table>"); out.println("</form>"); } out.println("</body>"); out.println("</html>");

Interfaz Servlet (despus de submit)

if (request.getParameter("btnSubmit") != null && request.getParameter("post_title") != null && request.getParameter("post_date") != null && request.getParameter("post_body") != null) { Posts nuevoPost = new Posts(); //manipulacion de la fecha nuevoPost.setPostDate(fechaSql); nuevoPost.setPostTitle(request.getParameter("post_title")); nuevoPost.setPostBody(request.getParameter("post_body")); nuevoPost.setPostId(this.getLastId()+1); this.persist(nuevoPost); response.sendRedirect("./SearchPost");

Potrebbero piacerti anche