Ejemplo de aplicación web con Hibernate que funciona usando Netbeans IDE y JSTL (JSP(X))

4.12.09. Por ooscarr (ooscarr)

Al final de este tutorial conocerás la dinámica del desarrollo de una aplicación web manejando la persistencia de la base de datos con Hibernate y cómo NetBeans IDE te ayuda a escribir el código y consultar la base de datos. También escribirás una aplicación web JSP que haga consultas a esta base de datos a través usando XML.

Este ejemplo de Hibernate es famoso, está documentado en varias páginas, pero todas tienen el código malo y es frustrante aprender así. Así que lo corregí y lo traduje al español sacando cosas de uno y de otro mismo tutorial que encontré en ¡chino, portugués, inglés y ruso!

Soporte para Hibernate en aplicaciones web está disponible desde NetBeans IDE 6.1. Desde NetBeans IDE 6.5, también puedes hacer ingeniería inversa a las tablas de una BD a archivos de mapeo y clases Java correspondientes usando un asistente intuitivo.

Pasos previos

Antes de empezar necesitarás:

  • Instalar NetBeans IDE. Al momento de escribir esto, anda dando vueltas la versión 6.8 RC2.
  • Instalar MySQL o Java DB, o tener acceso a conectarte a una de estas bases de datos con permiso para acceder o crear la base de datos Sakila. La base de datos Sakila está disponible en estos dos tipos de bases de datos, pero Hibernate funciona con cualquier JDBC, por ejemplo PostgreSQL y Oracle.
  • Importar la base de datos de ejemplo Sakila (a la que le haremos consultas en este ejemplo).

Una vez obtenido esto, asegúrate de configurar NetBeans IDE para poder acceder a la base de datos Sakila desde el panel "Prestaciones" (Menú Ventana > Prestaciones.

Instalar el complemento de Hibernate

El plug-in, si no lo tienes ya instalado, lo obtienes

  1. yendo, en el menú, a Herramientas > Complementos.
  2. En la ficha Plugins disponibles, selecciona la casilla del módulo Hibernate y presiona Instalar.

  3. Siguiente
  4. Acepta los términos de todos los contratos de licencia y presiona el botón de Instalar.
  5. Después que se descargue y se instale, presiona Terminar.
  6. Y listo, el módulo para Hibernate (o Hibernar) se activará solo; o sino, reinicia NetBeans IDE.

Crear Proyecto nuevo

Primero: lo típico. Creamos un Proyecto nuevo de tipo Aplicación web.

Asistente de Nuevo proyecto de NetBeans, bajo la categoría Web está la opción Aplicación web.

Para nuestro ejemplo, le damos el nombre DVDStore.

Elegimos un servidor como Tomcat o Glassfish, Siguiente y marcamos la opción Hibernate y seleccionamos la base de datos jdbc:mysql://localhost:3306/sakila, en nuestro caso, de la lista que, supongo, ya habías configurado anteriormente como indiqué en los pasos previos de este tutorial.

Asistente de Nuevo proyecto de NetBeans, después de marcar la casilla que habilita Hibernate 3.2.5 abajo selecciona la base de datos Sakila instalada en localhost.
Terminar

Fíjate que en:

  • DVDStore
    • Libraries

se agregaron automáticamente las librerías necesarias para utilizar Hibernate y conectar a la base de datos.

Configurar proyecto

hibernate.cfg.xml

Abre el archivo hibernate.cfg.xml que está en la ruta:

  • DVDStore
    • Source Packages
      • <paquete predeterminado>
        • hibernate.cfg.xml

Una vez abierto en NetBeans IDE, en el modo Diseño, en la parte Propiedades opcionales, Propiedades de configuración, pon Agregar... y añade la propiedad:

Nombre de la propiedad:hibernate.show_sql
Valor de la propiedad:true

Com el asistente de diseño de XML de configuración en NetBeans IDE se puede seleccionar los valores en una lista desplegable sin tocar el código XML.

Dentro de las mismas Propiedades opcionales del modo Diseño de NetBeans IDE, más abajo, en Propiedades varias, Agrega la propiedad:

Nombre de la propiedad:hibernate.current_session_context_class
Valor de la propiedad:thread

Después de esto, si ves el archivo hibernate.cfg.xml en el modo Operador XML, quedaría un código más o menos así, pero con otras contraseñas, por supuesto:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/sakila</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">######</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <property name="hibernate.show_sql">true</property>
  </session-factory>
</hibernate-configuration>

Guarda los cambios del archivo.

Asistente de ingeniería inversa de Hibernate

Agreguemos un nuevo archivo, y seleccionemos Hibernar > Asistente de ingeniería inversa de Hibernate

Asistente para la creación de nuevo archivo en NetBeans IDE. El primer paso es seleccionar la categoría Hibernar y luego, en la columna derecha, Asistente de ingeniería inversa de Hibernate

En el siguiente paso dejamos los valores por defecto (asegurándonos que pertenezca al proyecto DVDStore). Siguiente.

Se cargarán automáticamente los nombres de las tablas de la base de datos Sakila (elegida cuando creamos el proyecto), y seleccionaremos las tablas:

  • actor
  • category
  • film
  • film_actor
  • film_category
  • language

Asistente de ingeniería inversa de Hibernate tiene 2 columnas: Tablas disponibles (con las tablas en la base de datos) y Tablas seleccionadas (con las tablas que se utilizarán en el proyecto)
Para pasar tablas de una columnas a la otra, existen los botones Agregar > y < Eliminar.

Si marcas la casilla Incluir tablas relacionadas algunas otras tablas se incluirán automáticamente. Eso está bien.

Al presionar Terminar se va a crear un archivo hibernate.reveng.xml parecido a este:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd">
<hibernate-reverse-engineering>
  <schema-selection match-catalog="sakila"/>
  <table-filter match-name="film"/>
  <table-filter match-name="language"/>
  <table-filter match-name="category"/>
  <table-filter match-name="actor"/>
  <table-filter match-name="film_category"/>
  <table-filter match-name="film_actor"/>
</hibernate-reverse-engineering>

No lo edites, cíerralo.

Archivos de mapas de Hibernate y POJOs de la base de datos

Crea un Archivo nuevo.... Categoría Hibernar, tipo Archivos de mapas de Hibernate y POJOs de la base de datos.

Asistente para la creación de nuevo archivo en NetBeans IDE. El primer paso es seleccionar la categoría Hibernar y luego, en la columna derecha, Archivos de mapas de Hibernate y POJOs de la base de datos.

Debes ponerle nombre a la clase donde estarán los mapas de Hibernate. Para que este tutorial funcione, ponle dvdrental

En el asistente de nuevo archivo de mapas de Hibernate y POJOs de la base de datos, en el paso de la Generación de código, debes seleccionar hibernate.cfg.xml como archivo de configuración de Hibernate e hibernate.reveng.xml como archivo de ingeniería inversa.

...y presiona el botón Terminar. Se deberían generar los siguientes archivos:

  • DVDStore
    • Source Packages
      • dvdrental
        • Actor.hbm.xml
        • Actor.java
        • Category.hbm.xml
        • Category.java
        • Film.hbm.xml
        • Film.java
        • FilmActor.hbm.xml
        • FilmActor.java
        • FilmActorId.java
        • FilmCategory.hbm.xml
        • FilmCategory.java
        • FilmCategoryId.java
        • Language.hbm.xml
        • Language.java

HibernateUtil.java

Lo último sería crear un Archivo Nuevo..., Categoría Hibernar, Tipo HibernateUtil.java.

Al crear el nuevo archivo HibernateUtil.java, en el asistente de nuevo archivo de NetBeans IDE, por favor fijarse en cambiar el nombre del archivo propuesto NewHibernateUtil por HibernateUtil sin el New y agregarlo al paquete dvdrental
Terminar

Empecemos

FilmHelper.java

Crea una nueva Clase Java (Archivo Nuevo..., Categoría Java, tipo Clase Java) y llámale FilmHelper y ponlo dentro del paquete dvdrental.

Creación de una nueva clase Java llamada FilmHelper en el paquete dvdrental utilizando NetBeans IDE 6.8 para Mac OS X.
Terminar

Agrega el siguiente código (en negrita) para crear una sesión de Hibernate.

package dvdrental;

public class FilmHelper {

 Session session = null;

 public FilmHelper() {
  this.session = HibernateUtil.getSessionFactory().getCurrentSession();
 }

}

Van a aparecer unos errores que se arreglan usando el menú contextual (botón secundario del ratón) y eligiendo la opción Reparar importaciones.

Menú contextual aparece cuando uno hace click sobre el código fuente.
La opción Reparar importaciones en inglés se llama Fix import.

Si dejamos el valor por defecto, quedaría el código de FilmHelper.java de la siguiente manera:

package dvdrental;

import org.hibernate.Session;

public class FilmHelper {

 Session session = null;

 public FilmHelper() {
  this.session = HibernateUtil.getSessionFactory().getCurrentSession();
 }
 
}

Consultas HQL

Probemos algo. Haz click con el botón secundario sobre el archivo Source Packages/<paquete predeterminado>/hibernate.cfg.xml y selecciona la opción Ejecutar la consulta HQL del menú contextual.

Opción Ejecutar la consulta HQL aparece en el menú contextual sólo cuando se hace click sobre el archivo hibernate.cfg.xml.

En la barra de herramientas del editor de consultas HQL, selecciona la Sesión: hibernate.cfg y escribe lo siguiente en la primera caja de texto grande:

from Film

Y presiona el botón que está al lado de la lista desplegable que debería estar mostrando hibernate.cfg como opción seleccionada para hacer la consulta y obtener un resultado como el siguiente.

El Editor de consultas HQL de NetBeans IDE tiene dos partes: arriba para escribir la consultas y abajo para mostrar los resultados o equivalente SQL.

Ahora prueba con una consulta un poquito más complicada:

from Film as film where film.filmId between 100 and 200

Con las consultas probadas, obteniendo los resultados esperados, podemos utilizarlas en la clase helper.

Hibernate

Edita el archivo FilmHelper.java y agrégale el siguiente método (marcado con negrita):

package dvdrental;

import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;

public class FilmHelper {

 Session session = null;

 public FilmHelper() {
  this.session = HibernateUtil.getSessionFactory().getCurrentSession();
 }
 
  // Obtiene los films donde el id de film está entre un cierto rango especificado por las variables startID y endID

 public List getFilmTitles(int startID, int endID) {
  List<Film> filmList = null;
  try {
   org.hibernate.Transaction tx = session.beginTransaction();
   Query q = session.createQuery("from Film as film where film.filmId between '" + startID + "' and '" + endID + "'");
   filmList = (List<Film>) q.list();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return filmList;
 }
 
}

Repara las importaciones (Fix Import) si es necesario, utilizando las clases de hibernate.

Asistente para reparar importaciones en el código Java de NetBeans IDE. Instrucciones Import: Query org.hibernate.Query y List java.util.List.

para que quede completamente igual como está en el código de ejemplo anterior.

Vuelve a abrir el Editor de Consultas HQL y haz la siguiente query:

from Actor as actor where actor.actorId in (select filmActor.actor.actorId from FilmActor as filmActor where filmActor.film.filmId='10')

Esta consulta obtiene los actores de la película del filmid = 10.

Ahora súmale el siguiente método (marcado con negrita) al archivo FilmHelper.java:

package dvdrental;

import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;

public class FilmHelper {

 Session session = null;

 public FilmHelper() {
  this.session = HibernateUtil.getSessionFactory().getCurrentSession();
 }

  // Obtiene los films donde el id de film está entre un cierto rango especificado por las variables startID y endID

 public List getFilmTitles(int startID, int endID) {
  List<Film> filmList = null;
  try {
   org.hibernate.Transaction tx = session.beginTransaction();
   Query q = session.createQuery("from Film as film where film.filmId between '" + startID + "' and '" + endID + "'");
   filmList = (List<Film>) q.list();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return filmList;
 }

 // Obtiene los actores en un film particular
 public List getActorsByID(int filmId) {
  List<Actor> actorList = null;
  try {
   org.hibernate.Transaction tx = session.beginTransaction();
   Query q = session.createQuery("from Actor as actor where actor.actorId in (select filmActor.actor.actorId from FilmActor as filmActor where filmActor.film.filmId='" + filmId + "')");
   actorList = (List<Actor>) q.list();

  } catch (Exception e) {
   e.printStackTrace();
  }

  return actorList;
 }

}

Repara las importaciones si es necesario. Guarda.

Ahora agrega 3 métodos más y algunos métodos que inventé para hacer uso de beans en el código JSPX.


package dvdrental;

import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;

public class FilmHelper {

 Session session = null;

 public FilmHelper() {
  this.session = HibernateUtil.getSessionFactory().getCurrentSession();
 }

 // Obtiene los films donde el id de film está entre un cierto rango especificado por las variables startID y endID
 public List getFilmTitles(int startID, int endID) {
  List<Film> filmList = null;
  try {
   org.hibernate.Transaction tx = session.beginTransaction();
   Query q = session.createQuery("from Film as film where film.filmId between '" + startID + "' and '" + endID + "'");
   filmList = (List<Film>) q.list();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return filmList;
 }

 // Obtiene los actores en un film particular
 public List getActorsByID(int filmId) {
  List<Actor> actorList = null;
  try {
   org.hibernate.Transaction tx = session.beginTransaction();
   Query q = session.createQuery("from Actor as actor where actor.actorId in (select filmActor.actor.actorId from FilmActor as filmActor where filmActor.film.filmId='" + filmId + "')");
   actorList = (List<Actor>) q.list();

  } catch (Exception e) {
   e.printStackTrace();
  }

  return actorList;
 }

 // Obtiene una lista de categorías de acuerdo al filmId
 public Category getCategoryByID(int filmId) {
  List<Category> categoryList = null;
  try {
   org.hibernate.Transaction tx = session.beginTransaction();
   Query q = session.createQuery("from Category as category where category.categoryId in (select filmCat.category.categoryId from FilmCategory as filmCat where filmCat.film.filmId='" + filmId + "')");
   categoryList = (List<Category>) q.list();

  } catch (Exception e) {
   e.printStackTrace();
  }

  return categoryList.get(0);
 }

 // Obtiene un solo film de acuerdo al filmId
 public Film getFilmByID(int filmId) {

  Film film = null;

  try {
   org.hibernate.Transaction tx = session.beginTransaction();
   Query q = session.createQuery("from Film as film where film.filmId=" + filmId);
   film = (Film) q.uniqueResult();
  } catch (Exception e) {
   e.printStackTrace();
  }

  return film;
 }


 // Obtiene el idioma del film de acuerdo a un langId
 public String getLangByID(int langId) {

  Language language = null;

  try{
   org.hibernate.Transaction tx = session.beginTransaction();
   Query q = session.createQuery("from Language as lang where lang.languageId=" + langId);
   language = (Language) q.uniqueResult();
  } catch (Exception e) {
   e.printStackTrace();
  }

  return language.getName();
 }



 //Métodos para no poner código java en el JSPX
 int startId;
 int endId;

 int filmId;
 int langId;

 public void setAttributeStartID(int startId){
  this.startId = startId;
 }
 public void setAttributeEndID(int endId){
  this.endId = endId;
 }
 public List getFilmTitlesList(){
  return getFilmTitles(startId,endId);
 }
 public void setAttributeFilmByID(int filmId){
  this.filmId = filmId;
 }
 public List getActorsID() {
  return getActorsByID(filmId);
 }
 public Category getCategoryID() {
  return getCategoryByID(filmId);
 }
 public Film getFilmID() {
  return getFilmByID(filmId);
 }
 public void setAttributeLangByID(int langId){
  this.langId = langId;
 }
 public String getLangID() {
  return getLangByID(langId);
 }

}

JSP(X)

Hurra. Por fin llegamos a las páginas web. A mi me gusta escribir las JSP con JSTL así que antes de seguir deberás...

Instalar la librería JSTL

  1. Entra a las propiedades del proyecto (botón secundario del ratón sobre DVDStore, opción Propiedades).

  2. En la sección Libraries hay un botón Add Library.... Presiónalo.
  3. Si no te aparece inmediatamente, Importa la librería (o biblioteca también le llaman) JSTL 1.1 o superior.
  4. Selecciona la librería JSTL y añádela al proyecto.
  5. Aceptar

Nuevo archivo JSPX

Primero elimina el archivo index.jsp del proyecto que está en la carpeta DVDStore/Web Pages/ del proyecto.

Agrega un nuevo archivo JSPX y cambia la página por defecto.

En el archivo index.jspx escribe lo siguiente.

index.jspx
<?xml version="1.0" encoding="UTF-8"?>
<!-- 
    Document   : index
    Created on : 01-dic-2009, 21:43:16
    Author     : ooscarr
-->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
     xmlns:c="http://java.sun.com/jsp/jstl/core"
     xmlns:fn="http://java.sun.com/jsp/jstl/functions">

 <jsp:output
  omit-xml-declaration="no"
  doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
  doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
  doctype-root-element="html"/>

 <jsp:directive.page import="dvdrental.*"/>
 <jsp:directive.page import="java.util.List"/>

 <jsp:directive.page contentType="text/html" pageEncoding="UTF-8"/>

 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
   <title>DVDStore</title>
  </head>
  <body>


   <c:set var="startID" value="1"/>
   <c:set var="endID" value="10"/>
   <c:set var="prev_startID" value="1"/>
   <c:set var="prev_endID" value="10"/>
   
   <c:set var="FILM_RECORD_COUNT" value="1000"/>
   
   <c:set var="RECORD_START_PAGE" value="false"/>
   <c:set var="RECORD_END_PAGE" value="false"/>


   <c:if test="${not empty param.startid}">
    <c:set var="startID" value="${param.startid}"/>
   </c:if>
   <c:if test="${not empty param.endid}">
    <c:set var="endID" value="${param.endid}"/>
   </c:if>

   <jsp:useBean id="helper" class="dvdrental.FilmHelper"/>
   <!-- Invento para pasar filmID a FilmHelper.java -->
   <c:set target="${helper}" property="attributeStartID" value="${startID}"/>
   <c:set target="${helper}" property="attributeEndID" value="${endID}"/>
   <c:set var="filmTitles" value="${helper.filmTitlesList}"/>

   <c:if test="${startID == 1}">
    <c:set var="RECORD_START_PAGE" value="true"/>
   </c:if>
   <c:if test="${endID == FILM_RECORD_COUNT}">
    <c:set var="RECORD_END_PAGE" value="true"/>
   </c:if>

   <c:set var="prev_startID" value="${startID-10}"/>
   <c:set var="prev_endID" value="${endID-10}"/>

   <c:set var="startID" value="${endID+1}"/>
   <c:set var="endID" value="${endID+10}"/>

   <c:set var="filmTitlesSize" value="${fn:length(filmTitles)}"/>


   <table>
    <thead>

     <c:choose>
      <c:when test="${RECORD_START_PAGE}">
       <tr>
        <td class="NEXT"> </td>
        <td class="NEXT"> </td>
        <td class="NEXT"> </td>
        <td class="NEXT">
         <a class="NEXT" href="index.jspx?startid=${startID}&amp;endid=${endID}">Next</a></td>
       </tr>
      </c:when>
      <c:when test="${RECORD_END_PAGE}">
       <tr>
        <td class="NEXT"> </td>
        <td class="NEXT"> </td>
        <td class="NEXT">
         <a class="NEXT" href="index.jspx?startid=${prev_startID}&amp;endid=${prev_endID}">Prev</a></td>
        <td class="NEXT"> </td>
       </tr>
      </c:when>
      <c:otherwise>
       <tr>
        <td class="NEXT"> </td>
        <td class="NEXT"> </td>
        <td class="NEXT">
         <a class="NEXT" href="index.jspx?startid=${prev_startID}&amp;endid=${prev_endID}">Prev</a></td>
        <td class="NEXT">
         <a class="NEXT" href="index.jspx?startid=${startID}&amp;endid=${endID}">Next</a>
        </td>
       </tr>
      </c:otherwise>
     </c:choose>


     <tr><th>Title</th><th>Description</th><th> </th><th> </th></tr>
    </thead>
    <tbody>

     <c:forEach items="${filmTitles}" var="i">
      <c:set var="film" value="${i}"/>
      <c:set var="filmID" value="${film.filmId}"/>
      <tr>
       <td class="COL1">
        <a href="browse.jspx?id=${filmID}">${film.title}</a>
       </td>
       <td class="COL2">${film.description}</td>
       <td class="COL2">
        <a href="browse.jspx?id=${filmID}">More</a>
       </td>
       <td class="COL2">
        <a href="rent.jsp?id=${filmID}">Rent</a>
       </td>
      </tr>
     </c:forEach>

    </tbody>
   </table>

  </body>
 </html>
</jsp:root>

Ya lo puedes hacer correr si quieres probarlo.

Si no te gusta escribir las JSP con JSTL, puedes revisar el código oficial donde está lo mismo pero en clave Java clásico.

browse.jspx

Crea otro archivo JSP con sintaxis XML que se llame browse con el siguiente código:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
    Document   : browse
    Created on : 29-nov-2009, 19:47:16
    Author     : ooscarr
-->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
     xmlns:c="http://java.sun.com/jsp/jstl/core">

 <jsp:output
  omit-xml-declaration="no"
  doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
  doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
  doctype-root-element="html"/>

 <jsp:directive.page import="dvdrental.*"/>
 <jsp:directive.page import="java.util.List"/>

 <jsp:directive.page contentType="text/html" pageEncoding="UTF-8"/>

 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
   <title>DVDStore browse</title>
  </head>
  <body>
   
   <!-- Get title ID -->
   <c:set var="filmID" value="1"/>
   <c:if test="${not empty param.id}">
    <c:set var="filmID" value="${param.id}"/>
   </c:if>

   <c:set var="startPage">false</c:set>
   <c:set var="endPage">false</c:set>

   <jsp:useBean id="helper" class="dvdrental.FilmHelper"/>

   <!-- Invento para pasar filmID a FilmHelper.java -->
   <c:set target="${helper}" property="attributeFilmByID" value="${filmID}"/>

   <jsp:useBean id="film" class="dvdrental.Film"/>
   <c:set var="film" value="${helper.filmID}"/>

   <c:set var="filmTitle" value="${film.title}"/>
   <c:set var="filmDescription" value="${film.description}"/>

   <!-- Get Actors -->
   <c:set var="actors" value="${helper.actorsID}"/>

   <!-- Get Category -->
   <c:set var="category" value="${helper.categoryID}"/>

   <c:set var="totalCast">
    <c:forEach items="${actors}" var="i">${i.firstName} ${i.lastName}, </c:forEach>
   </c:set>

   <!-- Invento para pasar langId a FilmHelper.java -->
   <c:set target="${helper}" property="attributeLangByID" value="${film.languageByLanguageId.languageId}"/>
   <!-- Obtiene el idioma usando el langId entregado anteriormente -->
   <c:set var="language" value="${helper.langID}"/>
   
   <c:set var="filmLength" value="${film.length}"/>
   <c:set var="filmRating" value="${film.rating}"/>
   <c:set var="filmYear" value="${film.releaseYear}"/>
   
   <c:set var="rentalDuration" value="${film.rentalDuration}"/>
   <c:set var="rentalRate" value="${film.rentalRate}"/>

   <c:set var="specialFeatures" value="${film.specialFeatures}"/>


   <table>
    <tr>
     <td class="RENT"> </td>
     <td class="RENT">
      <a class="RENT" href="browse.jspx?id=${filmID}">Arrendar</a>
     </td>
    </tr>
    <tr>
     <th class="TITLE">Título</th>
     <td class="TITLE">${filmTitle}</td>
    </tr>
    <tr>
     <th class="COL1">Descripción</th>
     <td class="COL2">${filmDescription}</td>
    </tr>
    <tr>
     <td class="COL1"> </td>
     <td class="COL2"> </td>
    </tr>
    <tr>
     <th class="COL1">Género</th>
     <td class="COL2">${catName}</td>
    </tr>
    <tr>
     <td class="COL1"> </td>
     <td class="COL2"> </td>
    </tr>
    <tr>
     <th class="COL1">Reparto</th>
     <td class="COL2">${totalCast}</td>
    </tr>
    <tr>
     <td class="COL1"> </td>
     <td class="COL2"> </td>
    </tr>
    <tr>
     <th class="COL1">Duración de la película</th>
     <td class="COL2">${filmLength} <abbr title="minutos">mins.</abbr></td>
    </tr>
    <tr>
     <th class="COL1">Idioma</th>
     <td class="COL2">${language}</td>
    </tr>
    <tr>
     <th class="COL1">Calificación cinematográfica</th>
     <td class="COL2">${filmRating}</td>
    </tr>
    <tr>
     <th class="COL1">Año</th>
     <td class="COL2">${filmYear}</td>
    </tr>
    <tr>
     <td class="COL1"> </td>
     <td class="COL2"> </td>
    </tr>
    <tr>
     <th class="COL1">Características especiales</th>
     <td class="SPECIAL">${specialFeatures}</td>
    </tr>
    <tr>
     <td class="COL1"> </td>
     <td class="COL2"> </td>
    </tr>
    <tr>
     <th class="COL1">Precio Arriendo</th>
     <td class="COL2">US$ ${rentalRate}</td>
    </tr>
    <tr>
     <th class="COL1">Duración de Arriendo</th>
     <td class="COL2">${rentalDuration} días</td>
    </tr>
   </table>

   </body>
 </html>
</jsp:root>

Ejecuta la aplicación en el servidor, visita la página (en mi máquina se está ejecutando en http://localhost:8084/DVDStore/) y Voilà!. Funciona o te equivocaste.

Conclusiones

A pesar de que este ejemplo sólo hace lecturas a la base de datos, me puedo imaginar que escribir debe ser igual de sencillo ya que autmáticamente se generan la clases bean para insertar valores (set).

Con la persistencia ya no me tengo que preocupar de hacer la conexión y desconexión en cada página, la contraseña está guardada de manera más segura y estandarizada, y el acceso a las tablas se hace sencillo manejándolas como clases (un editor de Java ayuda a completar el código) y no andan las consultas SQL dando vueltas por todo el código, lo que ofrece mayor abstracción entre los distintos niveles del código otorgando flexibilidad a cambios.

Si se me ocurre cambiar la base de datos (agregar una columna, modificar el nombre de una tabla o las relaciones y tipos de datos), habría que regenerar los mapas de Hibernate y volver a compilar todo.

También, si nos fijamos en todo lo que hay que saber sobre programación Java, se hace más difícil la programación, aunque supongo y reconozco que con el tiempo se debe volver más sencillo con la experiencia. Obvio.

Mejoras en el rendimiento... No sé. Supongo que al tener todas las consultas guardadas... Y con Hibernate preocupado de las conexiones y desconexiones... Me imagino que sí hay alguna mejora, lo desconozco.

En el próximo capítulo...

Esto fue cómo leer desde una base de datos con Hibernate, prometo escribir sobre cómo escribir en la base de datos usando Hibernate y hacer este mismo ejemplo usando JPA, que ya lo tengo hecho, pero hay que desarrollarlo y darle formato. Hasta el próximo mes.

Referencias

Artículos relacionados

Etiquetas: , , , ,

6 comentarios (RSS ATOM) :

  1. A las 19/1/10 13:19  

    Blogger Miguel Angel Muguerza ha dicho...

    He avanzado con el jemplo pero en la clase "FilmHelper.java"


    me da error en la siguiente linea, parece que no se puede importar la clase "HibernateUtil"

    this.session = HibernateUtil.getSessionFactory().getCurrentSession();

    Alguien por favor ayudeme.


    Saludos!

  2. A las 22/1/10 12:23  

    Blogger alvaro ha dicho...

    Hola , me parece excelente tu página, con la poca informacion que hay , eres pionero en hibernate en español.

    con respecto al ejercicio mi fallo se da a que no reconoce en el tag

    html xmlns="http://www.w3.org/1999/xhtml"
    no reconoce el atributo xmlns.

    a que se deberá ??

  3. A las 22/1/10 14:15  

    OpenID elblog ha dicho...

    Con respecto a HibernateUtil, el asistente de Netbeans tiende a llamar al archivo nuevo "NewHibernateUtil". Revisa que el nombre del archivo sea correcto "HibernateUtil.java" y esté dentro del paquete dvdrental.

  4. A las 22/1/10 14:38  

    OpenID elblog ha dicho...

    @alvaro: ¿El archivo es terminado .jspx? Porque si no tiene la extensión con la X final, debes elegir la opción de "Sintaxis XML" en el asistente de nuevo JSP para que funcione mi código (o probar con la versión JSP sin sintaxis xml). Acabo de probar mi código y funciona.

  5. A las 25/1/10 15:24  

    Blogger alvaro ha dicho...

    Si , tambien segui tu ejemplo como hacer paginas .JSPX , pero ya lo solucioné. Si copias y pegas el codigo no te va a funcionar a menos que pegues el tag para terminar despues del tag final del html < /jsp:root >

  6. A las 9/2/10 20:47  

    Anonymous elblog ha dicho...

    Encontré un mucho mejor tutorial que soluciona el problema de las librerías obsoletas que incluye Netbeans (y por lo que falla con Tomcat) en esta dirección

Página principal

Publicidad