Upload
jesus-ismael-galan-cazares
View
192
Download
0
Embed Size (px)
Citation preview
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óduloHibernate 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.
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
datosjdbc: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.
Terminar
Fíjate que en:
DVDStore
o Libraries
se agregaron automáticamente las librerías necesarias para utilizarHibernate y conectar a la base de datos.
Configurar proyecto
hibernate.cfg.xml
Abre el archivo hibernate.cfg.xml que está en la ruta:
DVDStore
o Source Packages
<paquete predeterminado>
hibernate.cfg.xml
Una vez abierto en NetBeans IDE, en el modo Diseño, en la partePropiedades opcionales, Propiedades de configuración, ponAgregar... y añade la propiedad:
Nombre de la propiedad: hibernate.show_sql
Valor de la propiedad: true
Dentro de las mismas Propiedades opcionales del modo Diseño deNetBeans 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
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
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 archivohibernate.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.
Debes ponerle nombre a la clase donde estarán los mapas de Hibernate. Para
que este tutorial funcione, ponle dvdrental
...y presiona el botón Terminar. Se deberían generar los siguientes archivos:
DVDStore
o 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,
TipoHibernateUtil.java.
Terminar
Empecemos
FilmHelper.java
Crea una nueva Clase Java (Archivo Nuevo..., Categoría Java, tipoClase Java) y
llámale FilmHelper y ponlo dentro del paquetedvdrental.
Terminar
Agrega el siguiente código (en negrita) para crear una sesión deHibernate.
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.
La opción Reparar importaciones en inglés se llama Fix import.
Si dejamos el valor por defecto, quedaría el código deFilmHelper.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 archivoSource
Packages/<paquete predeterminado>/hibernate.cfg.xml y selecciona la
opción Ejecutar la consulta HQL del menú contextual.
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.
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.
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
archivoFilmHelper.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 JSPcon 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}&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}&endid=${prev_endID}">Prev</a></t
d>
<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}&endid=${prev_endID}">Prev</a></t
d>
<td class="NEXT">
<a class="NEXT"
href="index.jspx?startid=${startID}&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