Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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
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
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
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...
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
private int post_id; private String post_title; private Date post_date; private String post_body; //getter & setter methods
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:
Anotaciones (@)
Identidad
Ahora debemos incluir una nueva anotacin que permita definir el campo que identificar cada instancia de la entidad que estamos definiendo:
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
...
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):
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)
Persistencia:
postEntitypostObject=newpostEntity(); postObject.set();//definirvaloresparaelobjeto entityManager.persist(postObject);
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:
delete() es el mtodo de la clase EntityManager que permite eliminar una instancia de una entidad:
update() es el mtodo de la clase EntityManager que permite actualizar una instancia de una entidad:
flush() es el mtodo que sincroniza los cambios realizados sobre una entidad con la base de datos:
refresh() es el mtodo que devuelve los atributos de un objeto al ltimo estado recuperado desde la base de datos:
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:
Static Query II
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:
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();
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;
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 Entidad
Creacin Entidad
Creacin Entidad
Creacin Servlet
Creacin Servlet
Creacin Servlet
Asociando el EntityManager
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; }
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úsqueda:</td>"); out.println("<td>" + resultadoBusqueda.getPostTitle() + "</td>"); out.println("</tr>"); out.println("</table>");
} else { out.println("<table>"); out.println("<tr>"); out.println("<td>Su bú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>"); }
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
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();
//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(); }
} 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>");
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");