hibernate-orm/reference/es/modules/quickstart.xml

667 lines
31 KiB
XML

<chapter id="quickstart">
<title>Comienzo r&#x00e1;pido con Tomcat</title>
<sect1 id="quickstart-intro" revision="2">
<title>Empezando con Hibernate</title>
<para>
Este tutorial explica una instalaci&#x00f3;n de Hibernate con el
contenedor de servlets Apache Tomcat (hemos usado la versi&#x00f3;n 4.1,
las diferencias con la 5.0 deben ser m&#x00ed;nimas) para una aplicaci&#x00f3;n
basada en web. Hibernate trabaja bien en un entorno manejado con
todos los servidores de aplicaciones J2EE importantes, o incluso en aplicaciones
Java independientes. El sistema de base de datos es s&#x00f3;lo una cuesti&#x00f3;n
de cambiar la configuraci&#x00f3;n del dialecto SQL de Hibernate y las
propiedades de conexi&#x00f3;n.
</para>
<para>
Primero, tenemos que copiar todas las bibliotecas requeridas a la instalaci&#x00f3;n
de Tomcat. Usamos un contexto web separado (<literal>webapps/quickstart</literal>)
para este tutorial, de modo que tenemos que considerar tanto la ruta de b&#x00fa;squeda
de bibliotecas global (<literal>TOMCAT/common/lib</literal>) como tambi&#x00e9;n
el cargador de clases a nivel de contexto en <literal>webapps/quickstart/WEB-INF/lib</literal>
(para ficheros JAR) y <literal>webapps/quickstart/WEB-INF/classes</literal>.
Nos referiremos a ambos niveles de cargador de clases como el classpath global y el classpath
de contexto, respectivamente.
</para>
<para>
Ahora, copia las bibliotecas a los dos classpaths:
</para>
<orderedlist>
<listitem>
<para>
Copia el driver JDBC para la base de datos al classpath global. Esto se
requiere para el software de pool de conexiones DBCP que se distribuye
con Tomcat. Hibernate usa conexiones JDBC para ejecutar SQL sobre la base de
datos, de modo que, o bien tienes que proveer conexiones JDBC en pool,
o bien configurar Hibernate para que use uno de los pools soportados
directamente (C3P0, Proxool). Para este tutorial, copia la biblioteca
<literal>pg74jdbc3.jar</literal> (para PostgreSQL 7.4 y JDK 1.4) al
classpath del cargador global. Si quisieras usar una base de datos diferente,
simplemente copia su apropiado driver JDBC.
</para>
</listitem>
<listitem>
<para>
Nunca copies nada m&#x00e1;s dentro de la ruta del cargador de clases global
en Tomcat, o tendr&#x00e1;s problemas con varias herramientas, incluyendo
Log4J, commons-logging y otras. Siempre usa el classpath de contexto para
cada aplicaci&#x00f3;n web, esto es, copia las bibliotecas a
<literal>WEB-INF/lib</literal> y tus propias clases y ficheros de
configuraci&#x00f3;n/propiedades a <literal>WEB-INF/classes</literal>.
Ambos directorios est&#x00e1;n a nivel del classpath de contexto por defecto.
</para>
</listitem>
<listitem>
<para>
Hibernate est&#x00e1; empaquetado como una biblioteca JAR. El fichero
<literal>hibernate3.jar</literal> debe ser copiado en el classpath de contexto
junto a las otras clases de la aplicaci&#x00f3;n. Hibernate requiere algunas
bibliotecas de terceros en tiempo de ejecuci&#x00f3;n; &#x00e9;stas vienen
inclu&#x00ed;das con la distribuci&#x00f3;n de Hibernate en el directorio
<literal>lib/</literal>. Ver <xref linkend="3rdpartylibs"/>. Copia las
bibliotecas de terceros requeridas al classpath de contexto.
</para>
</listitem>
</orderedlist>
<table frame="topbot" id="3rdpartylibs">
<title>
Bibliotecas de terceros de Hibernate
</title>
<tgroup cols="2" rowsep="1" colsep="1">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="2*"/>
<thead>
<row>
<entry align="center">
Biblioteca
</entry>
<entry align="center">
Descripci&#x00f3;n
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
antlr (requerida)
</entry>
<entry>
Hibernate usa ANTLR para producir analizadores de consultas,
esta biblioteca tambi&#x00e9;n se necesita en tiempo de ejecuci&#x00f3;n.
</entry>
</row>
<row>
<entry>
dom4j (requerida)
</entry>
<entry>
Hibernate usa dom4j para analizar ficheros de configuraci&#x00f3;n
XML y ficheros de metadatos de mapeo XML.
</entry>
</row>
<row>
<entry>
CGLIB, asm (requerida)
</entry>
<entry>
Hibernate usa la biblioteca de generaci&#x00f3;n de c&#x00f3;digo
para aumentar las clases en tiempo de ejecuci&#x00f3;n
(en combinaci&#x00f3;n con reflecci&#x00f3;n Java).
</entry>
</row>
<row>
<entry>
Commons Collections, Commons Logging (requeridas)
</entry>
<entry>
Hibernate usa varias bibliotecas de utilidad del proyecto
Jakarta Commons de Apache.
</entry>
</row>
<row>
<entry>
EHCache (requerida)
</entry>
<entry>
Hibernate puede usar varios provedores de cach&#x00e9; para
el cach&#x00e9; de segundo nivel. EHCache es el provedor de
cach&#x00e9; por defecto si no se cambia en la configuraci&#x00f3;n.
</entry>
</row>
<row>
<entry>
Log4j (opcional)
</entry>
<entry>
Hibernate usa la API de Commons Logging, que a su vez puede
usar Log4J como el mecanismo de logging subyacente. Si la
biblioteca Log4J est&#x00e1; disponible en el directorio de
bibliotecas del contexto, Commons Logging usar&#x00e1; Log4J
y la configuraci&#x00f3;n <literal>log4j.properties</literal>
en el classpath de contexto. Un fichero de propiedades de ejemplo
para Log4J se incluye con la distribuci&#x00f3;n de Hibernate.
As&#x00ed; que copia log4j.jar y el fichero de configuraci&#x00f3;n
(de <literal>src/</literal>) a tu classpath de contexto si quieres
ver que ocurre tras esc&#x00e9;nas.
</entry>
</row>
<row>
<entry>
¿Requerida o no?
</entry>
<entry>
Echa una mirada al fichero <literal>lib/README.txt</literal> en la
distribuci&#x00f3;n de Hibernate. Esta es una lista actualizada
de bibliotecas de terceros distribu&#x00ed;das con Hibernate.
Encontrar&#x00e1;s listadas ah&#x00ed; todas las bibliotecas
requeridas y opcionales (Observa que "buildtame required" significa
aqu&#x00ed; para la construcci&#x00f3;n de Hibernate, no de tu
aplicaci&#x00f3;n).
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Ahora instalamos el pooling y modo compartido de conexiones de base de datos
tanto en Tomcat como Hibernate. Esto significa que Tomcat proveer&#x00e1;
conexiones JDBC en pool (usando su funcionalidad prefabricada de pooling DBCP).
Hibernate pide esas conexiones a trav&#x00e9;s de JNDI. Alternativamente,
puedes dejar que Hibernate maneje el pool de conexiones. Tomcat liga su pool
de conexiones a JNDI; agregamos una declaraci&#x00f3;n de recurso al fichero
de configuraci&#x00f3;n principal de Tomcat, <literal>TOMCAT/conf/server.xml</literal>:
</para>
<programlisting><![CDATA[<Context path="/quickstart" docBase="quickstart">
<Resource name="jdbc/quickstart" scope="Shareable" type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/quickstart">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<!-- DBCP database connection settings -->
<parameter>
<name>url</name>
<value>jdbc:postgresql://localhost/quickstart</value>
</parameter>
<parameter>
<name>driverClassName</name><value>org.postgresql.Driver</value>
</parameter>
<parameter>
<name>username</name>
<value>quickstart</value>
</parameter>
<parameter>
<name>password</name>
<value>secret</value>
</parameter>
<!-- DBCP connection pooling options -->
<parameter>
<name>maxWait</name>
<value>3000</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>100</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>10</value>
</parameter>
</ResourceParams>
</Context>]]></programlisting>
<para>
El contexto que configuramos en este ejemplo se llama <literal>quickstart</literal>,
su base es el directorio <literal>TOMCAT/webapp/quickstart</literal>. Para acceder
a cualquier servlet, llama a la ruta <literal>http://localhost:8080/quickstart</literal>
en tu navegador (por supuesto, agregando el nombre del servlet como se mapee en tu
<literal>web.xml</literal>). Puedes tambi&#x00e9;n ir m&#x00e1;s all&#x00e1; y crear
ahora un servlet simple que tenga un m&#x00e9;todo <literal>process()</literal>
vac&#x00ed;o.
</para>
<para>
Tomcat provee ahora conexiones a trav&#x00e9;s de JNDI en
<literal>java:comp/env/jdbc/quickstart</literal>. Si tienes problemas obteniendo
el pool de conexiones en ejecuci&#x00f3;n, refi&#x00e9;rete a la documentaci&#x00f3;n
de Tomcat. Si obtienes mensajes de excepci&#x00f3;n del driver JDBC, intenta instalar
primero el pool de conexiones JDBC sin Hibernate. Hay disponibles en la Web
tutoriales de Tomcat y JDBC.
</para>
<para>
Tu pr&#x00f3;ximo paso es configurar Hibernate. Hibernate tiene que saber c&#x00f3;mo
debe obtener conexiones JDBC. Usamos la configuraci&#x00f3;n de Hibernate basada en XML.
El otro enfoque, usando un ficheros de propiedad, es casi equivalente pero pierde unas
pocas funcionalidades que s&#x00ed; permite la sintaxis XML. El fichero de configuraci&#x00f3;n
XML se ubica en el classpath de contexto (<literal>WEB-INF/classes</literal>), como
<literal>hibernate.cfg.xml</literal>:
</para>
<programlisting><![CDATA[<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/quickstart</property>
<property name="show_sql">false</property>
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<!-- Mapping files -->
<mapping resource="Cat.hbm.xml"/>
</session-factory>
</hibernate-configuration>]]></programlisting>
<para>
Desactivamos el registro (logging) de comandos SQL y decimos a Hibernate
qu&#x00e9; dialecto SQL de base de datos se usa y d&#x00f3;nde obtener
conexiones JDBC (declarando la direcci&#x00f3;n JNDI del pool ligado a
Tomcat). El dialecto es una configuraci&#x00f3;n requerida, las bases de
datos difieren en su interpretaci&#x00f3;n del "est&#x00e1;ndar" de SQL.
Hibernate cuidar&#x00e1; de las diferencias y viene con dialectos inclu&#x00ed;dos
para todas las principales bases de datos comerciales y de c&#x00f3;digo
abierto.
</para>
<para>
Una <literal>SessionFactory</literal> es el concepto de Hibernate
de un almac&#x00e9;n de datos solo. Pueden usarse m&#x00fa;ltiples
bases de datos creando m&#x00fa;ltiples ficheros de configuraci&#x00f3;n
XML y creando m&#x00fa;ltiples objetos <literal>Configuration</literal>
y <literal>SessionFactory</literal> en tu aplicaci&#x00f3;n.
</para>
<para>
El &#x00fa;ltimo elemento del <literal>hibernate.cfg.xml</literal>
declara <literal>Cat.hbm.xml</literal> como el nombre de un fichero
de mapeo XML para la clase persistente <literal>Cat</literal>. Este
fichero contiene los metadatos para el mapeo de la clase POJO
<literal>Cat</literal> a una tabla (o tablas) de base de datos.
Volveremos a este fichero pronto. Escribamos primero la clase POJO
y luego declaremos los metadatos de mapeo para ella.
</para>
</sect1>
<sect1 id="quickstart-persistentclass" revision="1">
<title>Primera clase persistente</title>
<para>
Hibernate trabaja mejor con el modelo de programaci&#x00f3;n de los
Viejos Objetos Planos de Java (POJOs, a veces llamados Ordinarios Objetos Planos de Java)
para clases persistentes. Un POJO es como un JavaBean, con las propiedades
de la clase accesible v&#x00ed;a m&#x00e9;todos getter y setter,
encapsulando la representaci&#x00f3;n interna de la interfaz publicamente
visible (Hibernate puede tambi&#x00e9;n acceder a los campos directamente, si se
necesita):
</para>
<programlisting><![CDATA[package org.hibernate.examples.quickstart;
public class Cat {
private String id;
private String name;
private char sex;
private float weight;
public Cat() {
}
public String getId() {
return id;
}
private void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
}]]></programlisting>
<para>
Hibernate no est&#x00e1; restringido en su uso de tipos de propiedad, todos
los tipos y tipos primitivos del JDK de Java (como <literal>String</literal>,
<literal>char</literal> y <literal>Date</literal>) pueden ser mapeados, incluyendo
clases del framework de colecciones de Java. Puedes mapearlos como valores,
colecciones de valores, o asociaciones a otras entidades. El <literal>id</literal>
es una propiedad especial que representa el identificador de base de datos (clave
primaria) de la clase. Es altamente recomendado para entidades como un
<literal>Cat</literal>. Hibernate puede usar identificadores s&#x00f3;lo
internamente, pero perder&#x00ed;amos algo de la flexibilidad en nuestra
arquitectura de aplicaci&#x00f3;n.
</para>
<para>
No tiene que implementarse ninguna interface especial para las clases persistentes
ni tienes que subclasear de una clase persistente ra&#x00ed;z en especial. Hibernate
tampoco requiere ning&#x00fa;n procesamiento en tiempo de construcci&#x00f3;n,
como manipulaci&#x00f3;n del byte-code. Se basa solamente en reflecci&#x00f3;n de Java
y aumentaci&#x00f3;n de clases en tiempo de ejecuci&#x00f3;n (a trav&#x00e9;s de CGLIB).
De modo que, sin ninguna dependencia de la clase POJO en Hibernate, podemos mapearla
a una tabla de base de datos.
</para>
</sect1>
<sect1 id="quickstart-mapping" revision="1">
<title>Mapeando el gato</title>
<para>
El fichero de mapeo <literal>Cat.hbm.xml</literal> contiene los
metadatos requeridos para el mapeo objeto/relacional. Los metadatos
incluyen la declaraci&#x00f3;n de clases persistentes y el mapeo de
propiedades (a columnas y relaciones de claves for&#x00e1;neas a otras
entidades) a tablas de base de datos.
</para>
<programlisting><![CDATA[<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.hibernate.examples.quickstart.Cat" table="CAT">
<!-- A 32 hex character is our surrogate key. It's automatically
generated by Hibernate with the UUID pattern. -->
<id name="id" type="string" unsaved-value="null" >
<column name="CAT_ID" sql-type="char(32)" not-null="true"/>
<generator class="uuid.hex"/>
</id>
<!-- A cat has to have a name, but it shouldn' be too long. -->
<property name="name">
<column name="NAME" length="16" not-null="true"/>
</property>
<property name="sex"/>
<property name="weight"/>
</class>
</hibernate-mapping>]]></programlisting>
<para>
Cada clase persistente debe tener un atributo identificador (realmente,
s&#x00f3;lo las clases que representen entidades, no las clases dependientes
de tipo-valor, que son mapeadas como componentes de una entidad). Esta propiedad
es usada para distinguir los objetos persistentes: Dos gatos son iguales si
<literal>catA.getId().equals(catB.getId())</literal> es verdadero. Este concepto
se llama <emphasis>identidad de base de datos (database identity)</emphasis>.
Hibernate viene empaquetado con varios generadores de identificador para diferentes
escenarios (incluyendo generadores nativos para secuencias de base de datos, tablas
de identificadores alto/bajo, e identificadores asignados por aplicaci&#x00f3;n).
Usamos el generador UUID (recomendado s&#x00f3;lo para pruebas, pues deben
preferirse las claves enteras delegadas generadas por la base de datos) y
tambi&#x00e9;n especificamos la columna <literal>CAT_ID</literal> de la tabla
<literal>CAT</literal> para el valor identificador generado por Hibernate
(como una clave primaria de la tabla).
</para>
<para>
Todas las dem&#x00e1;s propiedades de <literal>Cat</literal> son mapeadas a la
misma tabla. En el caso de la propiedad <literal>name</literal>, la hemos mapeado
con una declaraci&#x00f3;n expl&#x00ed;cita de columna de base de datos. Esto es
especialmente &#x00fa;til cuando el esquema de base de datos es generado
autom&#x00e1;ticamente (como sentencias DDL de SQL) desde la declaraci&#x00f3;n
de mapeo con la herramienta <emphasis>SchemaExport</emphasis> de Hibernate.
Todas las dem&#x00e1;s propiedades son mapeadas usando la configuraci&#x00f3;n
por defecto de Hibernate, que es lo que necesitas la mayor&#x00ed;a del tiempo.
La tabla <literal>CAT</literal> en la base de datos se ve as&#x00ed; como:
</para>
<programlisting><![CDATA[ Columna | Tipo | Modificadores
--------+-----------------------+-----------
cat_id | character(32) | not null
name | character varying(16) | not null
sex | character(1) |
weight | real |
Indexes: cat_pkey primary key btree (cat_id)]]></programlisting>
<para>
Ahora debes crear esta tabla manualmente en tu base de datos, y luego leer el
<xref linkend="toolsetguide"/> si quieres automatizar este paso con la
herramienta <literal>hbm2ddl</literal>. Esta herramienta puede crear un
DDL SQL completo, incluyendo definici&#x00f3;n de tablas, restricciones
personalizadas de tipo de columnas, restricciones de unicidad e &#x00ed;ndices.
</para>
</sect1>
<sect1 id="quickstart-playingwithcats" revision="2">
<title>Jugando con gatos</title>
<para>
Ahora estamos listos para comenzar la <literal>Session</literal> de Hibernate.
Es el <emphasis>manejador de persistencia</emphasis> que usamos para almacenar
y traer <literal>Cat</literal>s hacia y desde la base de datos. Pero primero,
tenemos que obtener una <literal>Session</literal> (unidad de trabajo de Hibernate)
de la <literal>SessionFactory</literal>:
</para>
<programlisting><![CDATA[SessionFactory sessionFactory =
new Configuration().configure().buildSessionFactory();]]></programlisting>
<para>
La llamada a <literal>configure()</literal> carga el fichero de
configuraci&#x00f3;n <literal>hibernate.cfg.xml</literal> e
inicializa la instancia de <literal>Configuration</literal>.
Puedes establecer otras propiedades (e incluso cambiar los metadatos de mapeo)
accediendo a la <literal>Configuration</literal> <emphasis>antes</emphasis>
que construyas la <literal>SessionFactory</literal> (que es inmutable).
¿D&#x00f3;nde creamos la <literal>SessionFactory</literal> y c&#x00f3;mo
accedemos a ella en nuestra aplicaci&#x00f3;n?
</para>
<para>
Una <literal>SessionFactory</literal> usualmente se construye una vez,
por ejemplo, al arrancar con un servlet <emphasis>load-on-startup</emphasis>.
Esto significa tambi&#x00e9;n que no debes mantenerla en una variable de instancia
en tus servlets, sino en alguna otro sitio. Adem&#x00e1;s, necesitamos alg&#x00fa;n
tipo de <emphasis>Singleton</emphasis>, de modo que podamos acceder a la
<literal>SessionFactory</literal> f&#x00e1;cilmente en el c&#x00f3;digo de
aplicaci&#x00f3;n. El siguiente enfoque mostrado resuelve ambos problemas:
configuraci&#x00f3;n de arranque y f&#x00e1;cil acceso a una
<literal>SessionFactory</literal>.
</para>
<para>
Implementamos una clase de ayuda <literal>HibernateUtil</literal>:
</para>
<programlisting><![CDATA[import org.hibernate.*;
import org.hibernate.cfg.*;
public class HibernateUtil {
private static Log log = LogFactory.getLog(HibernateUtil.class);
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
log.error("Initial SessionFactory creation failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}
public static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() {
Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() {
Session s = (Session) session.get();
if (s != null)
s.close();
session.set(null);
}
}]]></programlisting>
<para>
Esta clase no s&#x00f3;lo cuida de la <literal>SessionFactory</literal>
con su inicializador static, sino que adem&#x00e1;s tiene una variable
<literal>ThreadLocal</literal> que tiene la <literal>Session</literal>
para la hebra actual. Aseg&#x00fa;rate de entender el concepto Java de una
variable local a una hebra antes de intentar usar esta ayuda. Una clase
<literal>HibernateUtil</literal> m&#x00e1;s compleja y potente puede
encontrarse en <literal>CaveatEmptor</literal>, http://caveatemptor.hibernate.org/
</para>
<para>
Una <literal>SessionFactory</literal> es segura entre hebras, muchas hebras pueden
acceder a ella concurrentemente y pedirle <literal>Session</literal>s. Una
<literal>Session</literal> no es un objeto seguro entre hebras que representa
una sola unidad-de-trabajo con la base de datos. Las <literal>Session</literal>s
se abren desde una <literal>SessionFactory</literal> y son cerradas cuando
todo el trabajo est&#x00e1; completo. Un ejemplo en el m&#x00e9;todo
<literal>process()</literal> de tu servlet podr&#x00ed;a parecerse a esto
(sin manejo de excepciones):
</para>
<programlisting><![CDATA[Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
Cat princess = new Cat();
princess.setName("Princess");
princess.setSex('F');
princess.setWeight(7.4f);
session.save(princess);
tx.commit();
HibernateUtil.closeSession();]]></programlisting>
<para>
En una <literal>Session</literal>, cada operaci&#x00f3;n de base de datos
ocurre dentro de una transacci&#x00f3;n que a&#x00ed;sla las operaciones
de base de datos (incluso operaciones de s&#x00f3;lo lectura).
Usamos la API de <literal>Transaction</literal> de Hibernate para
abstraer de la estrategia de transacciones subyacente (en nuestro caso,
transacciones JDBC). Esto permite que nuestro c&#x00f3;digo sea desplegado
con transacciones manejadas por contenedor (usando JTA) sin cambio alguno.
</para>
<para>
Observa que puedes llamar <literal>HibernateUtil.currentSession();</literal>
tantas veces como quieras, siempre obtendr&#x00e1;s la <literal>Session</literal>
actual de esta hebra. Tienes que asegurarte que la <literal>Session</literal>
sea cerrada despu&#x00e9;s que se complete tu unidad-de-trabajo, ya sea en
c&#x00f3;digo de tu servlet o en un filtro de servlet antes que la respuesta HTTP
sea enviada. El bonito efecto colateral de la segunda opci&#x00f3;n es la
f&#x00e1;cil inicializaci&#x00f3;n perezosa: la <literal>Session</literal> todav&#x00ed;a
est&#x00e1; abierta cuando se dibuja la vista, de modo que Hibernate puede cargar
objetos no inicializados mientras navegas tu actual grafo de objetos.
</para>
<para>
Hibernate tiene varios m&#x00e9;todos que pueden ser usados para traer
objetos desde la base de datos. La forma m&#x00e1;s flexible es usando
el Lenguaje de Consulta de Hibernate (Hibernate Query Language o HQL),
que es una extensi&#x00f3;n orientada a objetos de SQL f&#x00e1;cil de
aprender:
</para>
<programlisting><![CDATA[Transaction tx = session.beginTransaction();
Query query = session.createQuery("select c from Cat as c where c.sex = :sex");
query.setCharacter("sex", 'F');
for (Iterator it = query.iterate(); it.hasNext();) {
Cat cat = (Cat) it.next();
out.println("Female Cat: " + cat.getName() );
}
tx.commit();]]></programlisting>
<para>
Hibernate tambi&#x00e9;n ofrece una API <emphasis>consulta por criterios</emphasis>
orientada a objetos que puede ser usada para formular consultas de tipo seguro.
Por supuesto, Hibernate usa <literal>PreparedStatement</literal>s y ligado de
par&#x00e1;metros para toda la comunicaci&#x00f3;n SQL con la base de datos.
Tambi&#x00e9;n puedes usar la funcionalidad de consulta SQL directa de Hibernate
u obtener una conexi&#x00f3;n plana de JDBC de una <literal>Session</literal>
en casos raros.
</para>
</sect1>
<sect1 id="quickstart-summary" revision="1">
<title>Finalmente</title>
<para>
Rasgu&#x00f1;amos solamente la superficie de Hibernate en este peque&#x00f1;o
tutorial. Por favor, observa que no incluimos ning&#x00fa;n c&#x00f3;digo
espec&#x00ed;fico de servlet en nuestros ejemplos. Tienes que crear un servlet
por t&#x00ed; mismo e insertar el c&#x00f3;digo de Hibernate como lo veas
ubicado.
</para>
<para>
Ten en mente que Hibernate, como capa de acceso a datos, est&#x00e1; firmemente
integrado dentro de tu aplicaci&#x00f3;n. Usualmente, todas las otras capas dependen
del mecanismo de persistencia. Aseg&#x00fa;rate de entender las implicaciones
de este dise&#x00f1;o.
</para>
<para>
Para un ejemplo de aplicaci&#x00f3;n m&#x00e1;s compleja, ver
http://caveatemptor.hibernate.org/ y echa una mirada a los
otros tutoriales con links en http://www.hibernate.org/Documentation
</para>
</sect1>
</chapter>