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

1762 lines
85 KiB
XML

<chapter id="session-configuration" revision="1">
<title>Configuraci&#x00f3;n</title>
<para>
Debido a que Hibernate est&#x00e1; dise&#x00f1;ado para operar en muchos entornos
diferentes, hay un gran n&#x00fa;mero de par&#x00e1;metros de configuraci&#x00f3;n.
Afortunadamente, la mayor&#x00ed;a tiene valores por defecto sensibles e Hibernate
se distribuye con un fichero <literal>hibernate.properties</literal> de ejemplo en
<literal>etc/</literal> que muestra las diversas opciones. Tan s&#x00f3;lo pon el
fichero de ejemplo en tu classpath y personal&#x00ed;zalo.
</para>
<sect1 id="configuration-programmatic" revision="1">
<title>Configuraci&#x00f3;n program&#x00e1;tica</title>
<para>
Una instancia de <literal>org.hibernate.cfg.Configuration</literal>
representa un conjunto entero de mapeos de los tipos Java de una aplicaci&#x00f3;n
a una base de datos SQL. La <literal>Configuration</literal> es usada para
construir una <literal>SessionFactory</literal> (inmutable). Los mapeos se
compilan de varios ficheros de mapeo XML.
</para>
<para>
Puedes obtener una instancia de <literal>Configuration</literal> instanci&#x00e1;ndola
directamente y especificando documentos de mapeo XML. Si los ficheros de mapeo
est&#x00e1;n en el classpath, usa <literal>addResource()</literal>:
</para>
<programlisting><![CDATA[Configuration cfg = new Configuration()
.addResource("Item.hbm.xml")
.addResource("Bid.hbm.xml");]]></programlisting>
<para>
Una forma alternativa (a veces mejor) es especificar la clase mapeada,
y dejar que Hibernate encuentre el documento de mapeo por ti:
</para>
<programlisting><![CDATA[Configuration cfg = new Configuration()
.addClass(org.hibernate.auction.Item.class)
.addClass(org.hibernate.auction.Bid.class);]]></programlisting>
<para>
Entonces Hibernate buscar&#x00e1; ficheros de mapeo llamados
<literal>/org/hibernate/auction/Item.hbm.xml</literal> y
<literal>/org/hibernate/auction/Bid.hbm.xml</literal> en el classpath.
Este enfoque elimina cualquier nombre de fichero en el c&#x00f3;digo.
</para>
<para>
Una <literal>Configuration</literal> tambi&#x00e9;n te permite especificar
propiedades de configuraci&#x00f3;n:
</para>
<programlisting><![CDATA[Configuration cfg = new Configuration()
.addClass(org.hibernate.auction.Item.class)
.addClass(org.hibernate.auction.Bid.class)
.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect")
.setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test")
.setProperty("hibernate.order_updates", "true");]]></programlisting>
<para>
Esta no es la &#x00fa;nica forma de pasar propiedades de configuraci&#x00f3;n
a Hibernate. La diversas opciones incluyen:
</para>
<orderedlist spacing="compact">
<listitem>
<para>
Pasar una instancia de <literal>java.util.Properties</literal> a
<literal>Configuration.setProperties()</literal>.
</para>
</listitem>
<listitem>
<para>
Colocar <literal>hibernate.properties</literal> en un directorio
ra&#x00ed;z del classpath.
</para>
</listitem>
<listitem>
<para>
Establecer propiedades <literal>System</literal>
usando <literal>java -Dproperty=value</literal>.
</para>
</listitem>
<listitem>
<para>
Incluir elementos <literal>&lt;property&gt;</literal>
en <literal>hibernate.cfg.xml</literal> (discutido luego).
</para>
</listitem>
</orderedlist>
<para>
<literal>hibernate.properties</literal> es el enfoque m&#x00e1;s f&#x00e1;cil
si quieres comenzar r&#x00e1;pido.
</para>
<para>
La <literal>Configuration</literal> est&#x00e1; concebida como un objeto
de tiempo de arranque, para ser descartado una vez que una
<literal>SessionFactory</literal> es creada.
</para>
</sect1>
<sect1 id="configuration-sessionfactory">
<title>Obteniendo una SessionFactory</title>
<para>
Cuando todos los mapeos han sido parseados por la <literal>Configuration</literal>,
la aplicaci&#x00f3;n debe obtener una f&#x00e1;brica de instancias de <literal>Session</literal>.
Esta f&#x00e1;brica est&#x00e1; concebida para ser compartida por todas las hebras de
aplicaci&#x00f3;n:
</para>
<programlisting><![CDATA[SessionFactory sessions = cfg.buildSessionFactory();]]></programlisting>
<para>
Hibernate permite que tu aplicaci&#x00f3;n instancie m&#x00e1;s de una
<literal>SessionFactory</literal>. Esto es &#x00fa;til si est&#x00e1;s usando
m&#x00e1;s de una base de datos.
</para>
</sect1>
<sect1 id="configuration-hibernatejdbc" revision="1">
<title>Conexiones JDBC</title>
<para>
Usualmente, quieres que la <literal>SessionFactory</literal> cree y almacene
en pool conexiones JDBC para ti. Si adoptas este enfoque, abrir una <literal>Session</literal>
es tan simple como:
</para>
<programlisting><![CDATA[Session session = sessions.openSession(); // open a new Session]]></programlisting>
<para>
En cuanto hagas algo que requiera acceso a la base de datos, se obtendr&#x00e1; una
conexi&#x00f3;n JDBC del pool.
</para>
<para>
Para que esto funcione, necesitamos pasar algunas propiedades de conexi&#x00f3;n
JDBC a Hibernate. Todos los nombres de propiedades y su sem&#x00e1;ntica
est&#x00e1;n definidas en la clase <literal>org.hibernate.cfg.Environment</literal>.
Describiremos ahora las configuraciones m&#x00e1;s importantes para la conexi&#x00f3;n
JDBC.
</para>
<para>
Hibernate obtendr&#x00e1; (y tendr&#x00e1; en pool) conexiones usando
<literal>java.sql.DriverManager</literal> si configuras las siguientes propiedades:
</para>
<table frame="topbot">
<title>Propiedades JDBC de Hibernate</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="1*"/>
<thead>
<row>
<entry>Nombre de propiedad</entry>
<entry>Prop&#x00f3;sito</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>hibernate.connection.driver_class</literal>
</entry>
<entry>
<emphasis>clase del driver jdbc</emphasis>
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.url</literal>
</entry>
<entry>
<emphasis>URL de jdbc</emphasis>
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.username</literal>
</entry>
<entry>
<emphasis>usuario de base de datos</emphasis>
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.password</literal>
</entry>
<entry>
<emphasis>contrase&#x00f1;a del usuario de base de datos</emphasis>
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.pool_size</literal>
</entry>
<entry>
<emphasis>n&#x00fa;mero m&#x00e1;ximo de conexiones manejadas por pooling</emphasis>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
El algoritmo de pooling de conexiones propio de Hibernate es sin embargo
algo rudimentario. Est&#x00e1; concebido para ayudarte a comenzar y
<emphasis>no est&#x00e1; concebido para usar en un sistema de producci&#x00f3;n</emphasis>
ni siquiera para pruebas de rendimiento. Debes usar un pool de terceros para
un mejor rendimiento y estabilidad. S&#x00f3;lo remplaza la propiedad
<literal>hibernate.connection.pool_size</literal> con configuraciones
espec&#x00ed;ficas del pool de conexiones. Esto desactivar&#x00e1; el pool
interno de Hibernate. Por ejemplo, podr&#x00ed;as querer usar C3P0.
</para>
<para>
C3P0 es un pool de conexiones JDBC de c&#x00f3;digo abierto distribuido
junto a Hibernate en el directorio <literal>lib</literal>.
Hibernate usar&#x00e1; su <literal>C3P0ConnectionProvider</literal>
para pooling de conexiones si estableces propiedades <literal>hibernate.c3p0.*</literal>.
Si quieres usar Proxool refi&#x00e9;rete al <literal>hibernate.properties</literal>
empaquetado y al sitio web de Hibernate para m&#x00e1;s informaci&#x00f3;n.
</para>
<para>
Aqu&#x00ed; hay un fichero <literal>hibernate.properties</literal> de ejemplo para C3P0:
</para>
<programlisting id="c3p0-configuration" revision="1"><![CDATA[hibernate.connection.driver_class = org.postgresql.Driver
hibernate.connection.url = jdbc:postgresql://localhost/mydatabase
hibernate.connection.username = myuser
hibernate.connection.password = secret
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para>
Para su uso en un servidor de aplicaciones, casi siempre debes configurar
Hibernate para que obtenga conexiones de un <literal>Datasource</literal>
del servidor de aplicaciones registrado en JNDI. Necesitar&#x00e1;s establecer
al menos una de las siguientes propiedades:
</para>
<table frame="topbot">
<title>Propiedades de Datasource de Hibernate</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="1*"/>
<thead>
<row>
<entry>Nombre de propiedad</entry>
<entry>Prop&#x00f3;sito</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>hibernate.connection.datasource</literal>
</entry>
<entry>
<emphasis>nombre del datasource JNDI</emphasis>
</entry>
</row>
<row>
<entry>
<literal>hibernate.jndi.url</literal>
</entry>
<entry>
<emphasis>URL del provedor JNDI</emphasis> (optional)
</entry>
</row>
<row>
<entry>
<literal>hibernate.jndi.class</literal>
</entry>
<entry>
<emphasis>clase de la <literal>InitialContextFactory</literal> de JNDI</emphasis> (opcional)
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.username</literal>
</entry>
<entry>
<emphasis>usuario de base de datos</emphasis> (opcional)
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.password</literal>
</entry>
<entry>
<emphasis>contrase&#x00f1;a del usuario de base de datos</emphasis> (opcional)
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
He aqu&#x00ed; un fichero <literal>hibernate.properties</literal> de ejemplo
para un un datasource JNDI provisto por un servidor de aplicaciones.
</para>
<programlisting><![CDATA[hibernate.connection.datasource = java:/comp/env/jdbc/test
hibernate.transaction.factory_class = \
org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_lookup_class = \
org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para>
Las conexiones JDBC obtenidas de un datasource JNDI participar&#x00e1;n autom&#x00e1;ticamente
en las transacciones del servidor de aplicaciones manejadas por contenedor.
</para>
<para>
Pueden darse propiedades de conexi&#x00f3;n arbitrarias anteponiendo
"<literal>hibernate.connnection</literal>" al nombre de propiedad.
Por ejemplo, puedes especificar un <literal>charSet</literal> usando
<literal>hibernate.connection.charSet</literal>.
</para>
<para>
Puedes definir tu propia estrategia de plugin para obtener conexiones JDBC implementando
la interface <literal>org.hibernate.connection.ConnectionProvider</literal>. Puedes
seleccionar una implementaci&#x00f3;n personalizada estableciendo
<literal>hibernate.connection.provider_class</literal>.
</para>
</sect1>
<sect1 id="configuration-optional" revision="1">
<title>Par&#x00e1;metros de configuraci&#x00f3;n opcionales</title>
<para>
Hay un n&#x00fa;mero de otras propiedades que controlan el comportamiento
de Hibernate en tiempo de ejecuci&#x00f3;n. Todas son opcionales y tienen
valores por defecto razonables.
</para>
<para>
<emphasis>Advertencia: algunas de estas propiedades son de "nivel-de-sistema"
solamente.</emphasis>. Las propiedades a nivel de sistema s&#x00f3;lo pueden ser
establecidas por medio de <literal>java -Dproperty=value</literal> o
<literal>hibernate.properties</literal>. <emphasis>No</emphasis> pueden
establecerse por medio de las otras t&#x00e9;cnicas arriba descritas.
</para>
<table frame="topbot" id="configuration-optional-properties" revision="8">
<title>Propiedades de Configuraci&#x00f3;n de Hibernate</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="1*"/>
<thead>
<row>
<entry>Nombre de propiedad</entry>
<entry>Prop&#x00f3;sito</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>hibernate.dialect</literal>
</entry>
<entry>
El nombre de clase de un <literal>Dialect</literal>
de Hibernate que permite a Hibernate generar SQL optimizado
para una base de datos relacional en particular.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>full.classname.of.Dialect</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.show_sql</literal>
</entry>
<entry>
Escribe todas las sentencias SQL a la consola.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.default_schema</literal>
</entry>
<entry>
Cualifica, en el SQL generado, los nombres de tabla sin cualificar
con el esquema/tablespace dado.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>SCHEMA_NAME</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.default_catalog</literal>
</entry>
<entry>
Cualifica, en el SQL generado, los nombres de tabla sin cualificar
con el cat&#x00e1;logo dado.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>CATALOG_NAME</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.session_factory_name</literal>
</entry>
<entry>
La <literal>SessionFactory</literal> ser&#x00e1;
ligada a este nombre en JNDI autom&#x00e1;ticamente
despu&#x00e9;s de ser creada.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>jndi/composite/name</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.max_fetch_depth</literal>
</entry>
<entry>
Establece una "profundidad" m&#x00e1;xima del
&#x00e1;rbol de recuperaci&#x00f3;n por outer join
para asociaciones de un extremo solo (uno-a-uno, muchos-a-uno).
Un <literal>0</literal> deshabilita la recuperaci&#x00f3;n
por outer join por defecto.
<para>
<emphasis role="strong">ej.</emphasis>
valores recomendados entre <literal>0</literal> y
<literal>3</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.default_batch_fetch_size</literal>
</entry>
<entry>
Establece un tama&#x00f1;o por defecto para la recuperaci&#x00f3;n
en lote de asociaciones de Hibernate.
<para>
<emphasis role="strong">ej.</emphasis>
valores recomendados <literal>4</literal>, <literal>8</literal>,
<literal>16</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.default_entity_mode</literal>
</entry>
<entry>
Establece un modo por defecto de representaci&#x00f3;n de
entidades para todas las sesiones abiertas por esta
<literal>SessionFactory</literal>
<para>
<literal>dynamic-map</literal>, <literal>dom4j</literal>,
<literal>pojo</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.order_updates</literal>
</entry>
<entry>
Fuerza a Hibernate a ordenar las actualizaciones SQL
por el valor de la clave primaria de los items a actualizar.
Esto resultar&#x00e1; en menos bloqueos muertos de transacci&#x00f3;n
en sistemas altamente concurrentes.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.generate_statistics</literal>
</entry>
<entry>
De habilitarse, Hibernate colectar&#x00e1; estad&#x00ed;sticas
&#x00fa;tiles para la afinaci&#x00f3;n de rendimiento.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.use_identifer_rollback</literal>
</entry>
<entry>
De habilitarse, las propiedades identificadoras
generadas ser&#x00e1;n reseteadas a valores por
defecto cuando los objetos sean borrados.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.use_sql_comments</literal>
</entry>
<entry>
De activarse, Hibernate generar&#x00e1; comentarios dentro del SQL,
para una m&#x00e1;s f&#x00e1;cil depuraci&#x00f3;n, por defecto a
<literal>false</literal>.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table frame="topbot" id="configuration-jdbc-properties" revision="8">
<title>Propiedades de JDBC y Conexiones de Hibernate</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="1*"/>
<thead>
<row>
<entry>Nombre de propiedad</entry>
<entry>Propo&#x00f3;sito</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>hibernate.jdbc.fetch_size</literal>
</entry>
<entry>
Un valor distinto de cero que determina el tama&#x00f1;o
de recuperaci&#x00f3;n de JDBC (llama a
<literal>Statement.setFetchSize()</literal>).
</entry>
</row>
<row>
<entry>
<literal>hibernate.jdbc.batch_size</literal>
</entry>
<entry>
Un valor distinto de cero habilita el uso de actualizaciones
en lote de JDBC2 por Hibernate.
<para>
<emphasis role="strong">ej.</emphasis>
valores recomendados entre <literal>5</literal> y <literal>30</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.jdbc.batch_versioned_data</literal>
</entry>
<entry>
Establece esta propiedad a <literal>true</literal> si tu driver JDBC
devuelve cuentas correctas de filas desde <literal>executeBatch()</literal>
(usualmente es seguro activar esta opci&#x00f3;n). Hibernate usar&#x00e1;
DML en lote para versionar autom&#x00e1;ticamente los datos.
Por defecto a <literal>false</literal>.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.jdbc.factory_class</literal>
</entry>
<entry>
Selecciona un <literal>Batcher</literal> personalizado.
La mayor&#x00ed;a de las aplicaciones no necesitar&#x00e1;n
esta propiedad de configuraci&#x00f3;n.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>classname.of.Batcher</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.jdbc.use_scrollable_resultset</literal>
</entry>
<entry>
Habilita el uso de resultados scrollables de JDBC2 por Hibernate.
Esta propiedad s&#x00f3;lo es necesaria cuando se usan conexiones
JDBC provistas por el usuario, en caso contrario Hibernate usa los
metadatos de conexi&#x00f3;n.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.jdbc.use_streams_for_binary</literal>
</entry>
<entry>
Usa flujos (streams) al escribir/leer tipos
<literal>binary</literal> o <literal>serializable</literal>
a/desde JDBC (propiedad a nivel de sistema).
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.jdbc.use_get_generated_keys</literal>
</entry>
<entry>
Habilita el uso de <literal>PreparedStatement.getGeneratedKeys()</literal>
de JDBC3 para traer claves generadas nativamente despu&#x00e9;s de insertar.
Requiere un driver JDBC3+ y un JRE1.4+. Establ&#x00e9;cela a false si tu
driver tiene problemas con los generadores de identificador de Hibernate.
Por defecto, se intenta determinar las capacidades del driver usando los
metadatos de conexi&#x00f3;n.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true|false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.provider_class</literal>
</entry>
<entry>
EL nombre de clase de un <literal>ConnectionProvider</literal> personalizado
que provea conexiones JDBC a Hibernate.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>classname.of.ConnectionProvider</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.isolation</literal>
</entry>
<entry>
Establece el nivel de aislamiento de transacci&#x00f3;n JDBC.
Comprueba <literal>java.sql.Connection</literal> para valores
significativos pero observa que la mayor&#x00ed;a de las bases de
datos no soportan todos los niveles de aislamiento.
<para>
<emphasis role="strong">eg.</emphasis>
<literal>1, 2, 4, 8</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.autocommit</literal>
</entry>
<entry>
Habilita compromiso autom&#x00e1;tico (autocommit) para
las conexiones JDBC en pool (no recomendado).
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.release_mode</literal>
</entry>
<entry>
Especifica cu&#x00e1;ndo Hibernate debe liberar las conexiones JDBC.
Por defecto, una conexi&#x00f3;n JDBC es retenida hasta que la sesi&#x00f3;n
es cerrada expl&#x00ed;citamente o desconectada. Para un datasource JTA
del servidor de aplicaciones, debes usar <literal>after_statement</literal>
para liberar agresivamente las conexiones despu&#x00e9;s de cada llamada
JDBC. Para una conexi&#x00f3;n no JTA, frecuentemente tiene sentido liberar
la conexi&#x00f3;n al final de cada transacci&#x00f3;n, usando
<literal>after_transaction</literal>. <literal>auto</literal> eligir&#x00e1;
<literal>after_statement</literal> para las estrategias JTA o CMT
de transacci&#x00f3;n y <literal>after_transaction</literal> para la
estrategia JDBC de transacci&#x00f3;n.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>on_close</literal> (por defecto)| <literal>after_transaction</literal> |
<literal>after_statement</literal> | <literal>auto</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.connection.<emphasis>&lt;propertyName&gt;</emphasis></literal>
</entry>
<entry>
Pasa la propiedad JDBC <literal>propertyName</literal>
a <literal>DriverManager.getConnection()</literal>.
</entry>
</row>
<row>
<entry>
<literal>hibernate.jndi.<emphasis>&lt;propertyName&gt;</emphasis></literal>
</entry>
<entry>
Pasa la propiedad <literal>propertyName</literal>
a <literal>InitialContextFactory</literal> de JNDI.
</entry>
</row>
</tbody>
</tgroup>
</table>
<table frame="topbot" id="configuration-cache-properties" revision="7">
<title>Propiedades de Cach&#x00e9; de Hibernate</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="1*"/>
<thead>
<row>
<entry>Nombre de propiedad</entry>
<entry>Prop&#x00f3;sito</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>hibernate.cache.provider_class</literal>
</entry>
<entry>
El nombre de clase de un <literal>CacheProvider</literal> personalizado.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>classname.of.CacheProvider</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.cache.use_minimal_puts</literal>
</entry>
<entry>
Optimiza la operaci&#x00f3;n del cach&#x00e9; de segundo nivel
para minimizar escrituras, al costo de lecturas m&#x00e1;s frecuentes.
Esto es m&#x00e1;s &#x00fa;til para cach&#x00e9;s en cluster y,
en Hibernate3, est&#x00e1; habilitado por defecto para implementaciones
de cach&#x00e9; en cluster.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true|false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.cache.use_query_cache</literal>
</entry>
<entry>
Habilita el cach&#x00e9; de lectura, consultas individuales todav&#x00ed;a
tienen que ponerse cachables.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true|false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.cache.use_second_level_cache</literal>
</entry>
<entry>
Puede ser usado para deshabilitar completamente el cach&#x00e9;
de segundo nivel, que est&#x00e1; habilitado por defecto para clases
que especifican un mapeo <literal>&lt;cache&gt;</literal>.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true|false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.cache.query_cache_factory</literal>
</entry>
<entry>
El nombre de clase de una interface <literal>QueryCache</literal>
personalizada, por defecto al <literal>StandardQueryCache</literal>
prefabricado.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>classname.of.QueryCache</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.cache.region_prefix</literal>
</entry>
<entry>
Un prefijo a usar para los nombres de regi&#x00f3;n
del cach&#x00e9; de segundo nivel.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>prefix</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.cache.use_structured_entries</literal>
</entry>
<entry>
Fuerza a Hibernate a almacenar los datos en el cach&#x00e9;
de segundo nivel en un formato m&#x00e1;s amigable al humano.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true|false</literal>
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table frame="topbot" id="configuration-transaction-properties" revision="8">
<title>Propiedades de Transacci&#x00f3;n de Hibernate</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="1*"/>
<thead>
<row>
<entry>Nombre de propiedad</entry>
<entry>Prop&#x00f3;sito</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>hibernate.transaction.factory_class</literal>
</entry>
<entry>
El nombre de clase de un <literal>TransactionFactory</literal>
a usar con la API de <literal>Transaction</literal> de Hibernate
(por defectoa <literal>JDBCTransactionFactory</literal>).
<para>
<emphasis role="strong">ej.</emphasis>
<literal>classname.of.TransactionFactory</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>jta.UserTransaction</literal>
</entry>
<entry>
Un nombre JNDI usado por <literal>JTATransactionFactory</literal> para
obtener la <literal>UserTransaction</literal> JTA del servidor
de aplicaciones.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>jndi/composite/name</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.transaction.manager_lookup_class</literal>
</entry>
<entry>
El nombre de clase de un <literal>TransactionManagerLookup</literal>
requerido cuando el chach&#x00e9; a nivel de JVM est&#x00e1;
habilitado o cuando se usa un generador alto/bajo en un
entorno JTA.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>classname.of.TransactionManagerLookup</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.transaction.flush_before_completion</literal>
</entry>
<entry>
De habilitarse, la sesi&#x00f3;n se limpiar&#x00e1; (flushed)
autom&#x00e1;ticamente durante la fase previa a la compleci&#x00f3;n
de la transacci&#x00f3;n. (Muy &#x00fa;til cuando se usa Hibernate
con CMT).
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.transaction.auto_close_session</literal>
</entry>
<entry>
De habilitarse, la sesi&#x00f3;n ser&#x00e1; cerrada autom&#x00e1;ticamente
durante la fase posterior a la compleci&#x00f3;n de la transacci&#x00f3;n.
(Muy &#x00fa;til cuando se usa Hibernate con CMT).
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table frame="topbot" id="configuration-misc-properties" revision="7">
<title>Propiedades Miscel&#x00e1;neas</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="1*"/>
<thead>
<row>
<entry>Nombre de propiedad</entry>
<entry>Prop&#x00f3;sito</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>hibernate.query.factory_class</literal>
</entry>
<entry>
Elige la implementaci&#x00f3;n de parser HQL.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>org.hibernate.hql.ast.ASTQueryTranslatorFactory</literal> or
<literal>org.hibernate.hql.classic.ClassicQueryTranslatorFactory</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.query.substitutions</literal>
</entry>
<entry>
Mapeos de s&#x00ed;mbolos en consultas Hibernate a
s&#x00ed;mbolos SQL. (los s&#x00ed;mbolos puedem ser
nombres de funci&#x00f3;n o literales, por ejemplo).
<para>
<emphasis role="strong">ej.</emphasis>
<literal>hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.hbm2ddl.auto</literal>
</entry>
<entry>
Exporta autom&#x00e1;ticamente DDL de esquema cuando
al crear la <literal>SessionFactory</literal>.
Con <literal>create-drop</literal>, el esquema de
base de datos ser&#x00e1; desechado cuando la
<literal>SessionFactory</literal> se cierre expl&#x00ed;citamente.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>update</literal> | <literal>create</literal> | <literal>create-drop</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.cglib.use_reflection_optimizer</literal>
</entry>
<entry>
Habilita el uso de CGLIB en vez de reflecc&#x00f3;n en tiempo de
ejecuci&#x00f3;n (propiedad a nivel de sistema). La reflecci&#x00f3;n
a veces puede ser &#x00fa;til ante la aparici&#x00f3;n de problemas.
Observa que Hibernate siempre requiere CGLIB incluso si desactivas
el optimizador. No puedes establecer esta propiedad en
<literal>hibernate.cfg.xml</literal>.
<para>
<emphasis role="strong">ej.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<sect2 id="configuration-optional-dialects" revision="1">
<title>SQL Dialects</title>
<para>
You should always set the <literal>hibernate.dialect</literal> property to the correct
<literal>org.hibernate.dialect.Dialect</literal> subclass for your database. If you
specify a dialect, Hibernate will use sensible defaults for some of the
other properties listed above, saving you the effort of specifying them manually.
</para>
<table frame="topbot" id="sql-dialects" revision="2">
<title>Dialectos SQL de Hibernate(<literal>hibernate.dialect</literal>)</title>
<tgroup cols="2">
<colspec colwidth="1*"/>
<colspec colwidth="2.5*"/>
<thead>
<row>
<entry>RDBMS</entry>
<entry>Dialecto</entry>
</row>
</thead>
<tbody>
<row>
<entry>DB2</entry> <entry><literal>org.hibernate.dialect.DB2Dialect</literal></entry>
</row>
<row>
<entry>DB2 AS/400</entry> <entry><literal>org.hibernate.dialect.DB2400Dialect</literal></entry>
</row>
<row>
<entry>DB2 OS390</entry> <entry><literal>org.hibernate.dialect.DB2390Dialect</literal></entry>
</row>
<row>
<entry>PostgreSQL</entry> <entry><literal>org.hibernate.dialect.PostgreSQLDialect</literal></entry>
</row>
<row>
<entry>MySQL</entry> <entry><literal>org.hibernate.dialect.MySQLDialect</literal></entry>
</row>
<row>
<entry>MySQL con InnoDB</entry> <entry><literal>org.hibernate.dialect.MySQLInnoDBDialect</literal></entry>
</row>
<row>
<entry>MySQL con MyISAM</entry> <entry><literal>org.hibernate.dialect.MySQLMyISAMDialect</literal></entry>
</row>
<row>
<entry>Oracle (cualquier versi&#x00f3;n)</entry> <entry><literal>org.hibernate.dialect.OracleDialect</literal></entry>
</row>
<row>
<entry>Oracle 9i/10g</entry> <entry><literal>org.hibernate.dialect.Oracle9Dialect</literal></entry>
</row>
<row>
<entry>Sybase</entry> <entry><literal>org.hibernate.dialect.SybaseDialect</literal></entry>
</row>
<row>
<entry>Sybase Anywhere</entry> <entry><literal>org.hibernate.dialect.SybaseAnywhereDialect</literal></entry>
</row>
<row>
<entry>Microsoft SQL Server</entry> <entry><literal>org.hibernate.dialect.SQLServerDialect</literal></entry>
</row>
<row>
<entry>SAP DB</entry> <entry><literal>org.hibernate.dialect.SAPDBDialect</literal></entry>
</row>
<row>
<entry>Informix</entry> <entry><literal>org.hibernate.dialect.InformixDialect</literal></entry>
</row>
<row>
<entry>HypersonicSQL</entry> <entry><literal>org.hibernate.dialect.HSQLDialect</literal></entry>
</row>
<row>
<entry>Ingres</entry> <entry><literal>org.hibernate.dialect.IngresDialect</literal></entry>
</row>
<row>
<entry>Progress</entry> <entry><literal>org.hibernate.dialect.ProgressDialect</literal></entry>
</row>
<row>
<entry>Mckoi SQL</entry> <entry><literal>org.hibernate.dialect.MckoiDialect</literal></entry>
</row>
<row>
<entry>Interbase</entry> <entry><literal>org.hibernate.dialect.InterbaseDialect</literal></entry>
</row>
<row>
<entry>Pointbase</entry> <entry><literal>org.hibernate.dialect.PointbaseDialect</literal></entry>
</row>
<row>
<entry>FrontBase</entry> <entry><literal>org.hibernate.dialect.FrontbaseDialect</literal></entry>
</row>
<row>
<entry>Firebird</entry> <entry><literal>org.hibernate.dialect.FirebirdDialect</literal></entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<sect2 id="configuration-optional-outerjoin" revision="4">
<title>Recuperaci&#x00f3;n por Uni&#x00f3;n Externa (Outer Join Fetching)</title>
<para>
Si tu base de datos soporta uniones externas del estilo ANSI, Oracle o Sybase, la
<emphasis>recuperaci&#x00f3;n por uni&#x00f3;n externa</emphasis> aumentar&#x00e1;
frecuentemente el rendimiento limitando el n&#x00fa;mero de llamadas a la base de datos
(al costo de m&#x00e1;s trabajo posiblemente realizado por la base de datos misma).
La recuperaci&#x00f3;n por uni&#x00f3;n externa permite que un grafo completo de objetos
conectados por asociaciones muchos-a-uno, uno-a-muchos, muchos-a-muchos y uno-a-uno sea
tra&#x00ed;do en una sola <literal>SELECT</literal> SQL.
</para>
<para>
La recuperaci&#x00f3;n por uni&#x00f3;n externa puede ser deshabilitada
<emphasis>globalmente</emphasis> estableciendo la propiedad
<literal>hibernate.max_fetch_depth</literal> a <literal>0</literal>.
Un valor de <literal>1</literal> o mayor habilita la recuperaci&#x00f3;n
por uni&#x00f3;n externa para asociaciones uno-a-uno y muchos-a-uno que
hayan sido mapeadas con <literal>fetch="join"</literal>.
</para>
<para>
Ver <xref linkend="performance-fetching"/> para m&#x00e1;s informaci&#x00f3;n.
</para>
</sect2>
<sect2 id="configuration-optional-binarystreams" revision="1">
<title>Flujos Binarios</title>
<para>
Oracle limita el tama&#x00f1;o de arrays de <literal>byte</literal>
que puedan ser pasados a/desde su driver JDBC. Si deseas usar instancias
grandes de tipo <literal>binary</literal> o <literal>serializable</literal>,
debes habilitar <literal>hibernate.jdbc.use_streams_for_binary</literal>.
<emphasis>Esta es una propiedad a nivel de sistema solamente.</emphasis>
</para>
</sect2>
<sect2 id="configuration-optional-cacheprovider" revision="2">
<title>Cach&#x00e9; de segundo nivel y de lectura</title>
<para>
Las propiedades prefijadas por <literal>hibernate.cache</literal>
te permiten usar un sistema de cach&#x00e9; de segundo nivel
en el &#x00e1;mbito de un proceso o cluster con Hibernate.
Ver <xref linkend="performance-cache"/> para m&#x00e1;s detalles.
</para>
</sect2>
<sect2 id="configuration-optional-querysubstitution">
<title>Sustituci&#x00f3;n de Lenguaje de Consulta</title>
<para>
Puedes definir nuevos s&#x00ed;mbolos de consulta de Hibernate usando
<literal>hibernate.query.substitutions</literal>. Por ejemplo:
</para>
<programlisting>hibernate.query.substitutions true=1, false=0</programlisting>
<para>
causar&#x00ed;a que los s&#x00ed;mbolos <literal>true</literal> y <literal>false</literal> sean
traducidos a literales enteros en el SQL generado.
</para>
<programlisting>hibernate.query.substitutions toLowercase=LOWER</programlisting>
<para>
te permitir&#x00ed;a renombrar la funci&#x00f3;n <literal>LOWER</literal> de SQL.
</para>
</sect2>
<sect2 id="configuration-optional-statistics" revision="2">
<title>Hibernate statistics</title>
<para>
Si habilitas <literal>hibernate.generate_statistics</literal>, Hibernate
expondr&#x00e1; un n&#x00fa;mero de m&#x00e9;tricas que son &#x00fa;tiles
al afinar un sistema en ejecuci&#x00f3;n v&#x00ed;a
<literal>SessionFactory.getStatistics()</literal>. Hibernate puede incluso ser
configurado para exponer estas estad&#x00ed;sticas v&#x00ed;a JMX. Lee el
Javadoc de las interfaces en <literal>org.hibernate.stats</literal>
para m&#x00e1;s informaci&#x00f3;n.
</para>
</sect2>
</sect1>
<sect1 id="configuration-logging">
<title>Registros de mensajes (Logging)</title>
<para>
Hibernate registra varios eventos usando commons-logging
de Apache.
</para>
<para>
El servicio de commons-logging saldr&#x00e1; directamente ya sea a
Log4J (si incluyes <literal>log4j.jar</literal> in your classpath) o
JDK1.4 logging (al ejecutar bajo JDK1.4 o superior). Puedes descargar
Log4J desde <literal>http://logging.apache.org</literal>. Para usar
Log4J necesitar&#x00e1;s colocar un fichero <literal>log4j.properties</literal>
en tu classpath. Un fichero de propiedades de ejemplo se distribuye con
Hibernate en el directorio <literal>src/</literal>.
</para>
<para>
Recomendamos fuertemente que te familiarices con los registros de mensajes
de Hibernate. Se ha puesto un gran trabajo en hacer los registros de Hibernate
tan detallados como se puede, sin hacerlos ilegibles. Es un dispositivo esencial
en la resoluci&#x00f3;n de problemas. Las categor&#x00ed;as de registro
m&#x00e1;s interesantes son las siguientes:
</para>
<table frame="topbot" id="log-categories" revision="2">
<title>Categor&#x00ed;as de Registro de Hibernate</title>
<tgroup cols="2">
<colspec colwidth="1*"/>
<colspec colwidth="2.5*"/>
<thead>
<row>
<entry>Categor&#x00ed;a</entry>
<entry>Funci&#x00f3;n</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>org.hibernate.SQL</literal></entry>
<entry>Registra todas las sentencias DML de SQL a
medida que se ejecutan</entry>
</row>
<row>
<entry><literal>org.hibernate.type</literal></entry>
<entry>Registra todos los par&#x00e1;metros JDBC</entry>
</row>
<row>
<entry><literal>org.hibernate.tool.hbm2ddl</literal></entry>
<entry>Registra todas las sentencias DDL de SQL a
medida que se ejecutan</entry>
</row>
<row>
<entry><literal>org.hibernate.pretty</literal></entry>
<entry>
Registra el estado de todas las entidades (m&#x00e1;ximo
de 20 entidades) asociadas con la sesi&#x00f3;n en tiempo
de limpieza (flush)
</entry>
</row>
<row>
<entry><literal>org.hibernate.cache</literal></entry>
<entry>Registra toda la actividad del cach&#x00e9; de segundo nivel</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction</literal></entry>
<entry>Registra la actividad relacionada con la transacci&#x00f3;n</entry>
</row>
<row>
<entry><literal>org.hibernate.jdbc</literal></entry>
<entry>Registra toda adquisici&#x00f3;n de recursos JDBC</entry>
</row>
<row>
<entry><literal>org.hibernate.hql.ast</literal></entry>
<entry>Regista los ASTs de HQL y SQL, as&#x00ed; como
otra informaci&#x00f3;n sobre an&#x00e1;lisis de consultas.</entry>
</row>
<row>
<entry><literal>org.hibernate.secure</literal></entry>
<entry>Registra todas las peticiones de autorizaci&#x00f3;n JAAS</entry>
</row>
<row>
<entry><literal>org.hibernate</literal></entry>
<entry>
Registra todo (mucha informaci&#x00f3;n, pero muy &#x00fa;til
para la resoluci&#x00f3;n de problemas)
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Al desarrollar aplicacinoes con Hibernate, casi siempre debes trabajar con
<literal>debug</literal> habilitado para la categor&#x0ed;a <literal>org.hibernate.SQL</literal>
o, alternativamente, la propiedad <literal>hibernate.show_sql</literal> habilitada.
</para>
</sect1>
<sect1 id="configuration-namingstrategy">
<title>Implementando una <literal>NamingStrategy</literal></title>
<para>
La interface <literal>org.hibernate.cfg.NamingStrategy</literal> te permite
especificar un "est&#x00e1;ndar de nombrado" para objetos de la base de datos
y elementos de esquema.
</para>
<para>
Puedes proveer reglas para generar autom&#x00e1;ticamente identificadores de
base de datos a partir de identificadores JDBC o para procesar nombres
"l&#x00f3;gicos" de columnas y tablas dados en el fichero de mapeo en nombres
"f&#x00ed;sicos" de columnas y tablas. Esta funcionalidad ayuda a reducir
la verborragia del documento de mapeo, eliminando ruido repetitivo
(prefijos <literal>TBL_</literal>, por ejemplo). La estrategia por defecto
usada por Hibernate m&#x00ed;nima en absoluto.
</para>
<para>
Puedes especificar una estrategia diferente llamando a
<literal>Configuration.setNamingStrategy()</literal> antes de agregar los mapeos:
</para>
<programlisting><![CDATA[SessionFactory sf = new Configuration()
.setNamingStrategy(ImprovedNamingStrategy.INSTANCE)
.addFile("Item.hbm.xml")
.addFile("Bid.hbm.xml")
.buildSessionFactory();]]></programlisting>
<para>
<literal>org.hibernate.cfg.ImprovedNamingStrategy</literal>
es una estrategia prefabricada que puede ser un punto de
partida &#x00fa;til para algunas aplicaciones.
</para>
</sect1>
<sect1 id="configuration-xmlconfig" revision="2">
<title>Fichero de configuraci&#x00f3;n XML</title>
<para>
Un enfoque alternativo de configuraci&#x00f3;n es especificar una
configuraci&#x00f3;n completa en un fichero llamado <literal>hibernate.cfg.xml</literal>.
Este fichero puede ser usado como un remplazo del fichero <literal>hibernate.properties</literal> o,
si ambos est&#x00e1;n presentes, para sobrescribir propiedades.
</para>
<para>
El fichero de configuraci&#x00f3;n XML se espera por defecto en la
ra&#x00ed;z o tu <literal>CLASSPATH</literal>. He aqu&#x00ed; un ejemplo:
</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>
<!-- a SessionFactory instance listed as /jndi/name -->
<session-factory
name="java:hibernate/SessionFactory">
<!-- properties -->
<property name="connection.datasource">java:/comp/env/jdbc/MyDB</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">false</property>
<property name="transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</property>
<property name="jta.UserTransaction">java:comp/UserTransaction</property>
<!-- mapping files -->
<mapping resource="org/hibernate/auction/Item.hbm.xml"/>
<mapping resource="org/hibernate/auction/Bid.hbm.xml"/>
<!-- cache settings -->
<class-cache class="org.hibernate.auction.Item" usage="read-write"/>
<class-cache class="org.hibernate.auction.Bid" usage="read-only"/>
<collection-cache collection="org.hibernate.auction.Item.bids" usage="read-write"/>
</session-factory>
</hibernate-configuration>]]></programlisting>
<para>
Como puedes ver, la ventaja de este enfoque es la externalizaci&#x00f3;n de los
nombres de los fichero de mapeo a configuraci&#x00f3;n. El
<literal>hibernate.cfg.xml</literal> es tambi&#x00e9;n m&#x00e1;s conveniente
una vez que hayas afinado el cach&#x00e9; de Hibernate. Observa que elecci&#x00f3;n
tuya usar ya sea <literal>hibernate.properties</literal> o
<literal>hibernate.cfg.xml</literal>, ambos son equivalentes, excepto por los
beneficios de usar la sintaxis XML arriba mencionados.
</para>
<para>
Con la configuraci&#x00f3;n XML, arrancar Hibernate es tan simple como
</para>
<programlisting><![CDATA[SessionFactory sf = new Configuration().configure().buildSessionFactory();]]></programlisting>
<para>
Puedes tomar un fichero XML diferente usando
</para>
<programlisting><![CDATA[SessionFactory sf = new Configuration()
.configure("catdb.cfg.xml")
.buildSessionFactory();]]></programlisting>
</sect1>
<sect1 id="configuration-j2ee" revision="1">
<title>Integraci&#x00f3; con Servidores de Aplicaciones J2EE</title>
<para>
Hibernate tiene los siguientes puntos de integraci&#x00f3;n con la
infraestructura J2EE:
</para>
<itemizedlist>
<listitem>
<para>
<emphasis>Datasources manejados por contenedor</emphasis>: Hibernate puede usar
conexiones JDBC manejadas por el contenedor y provistas a trav&#x00e9;s de JNDI.
Usualmente, un <literal>TransactionManager</literal> compatible con JTA y un
<literal>ResourceManager</literal> cuidan del manejo de transacciones (CMT),
esp. manejo de transacciones distribu&#x00ed;das a trav&#x00e9;s de varios
datasources. Puedes tambi&#x00e9;n, por supuesto, demarcar los l&#x00ed;mites
de las transacciones program&#x00e1;ticamente (BMT) o podr&#x00ed;as querer usar
para esto la API opcional de <literal>Transaction</literal> de Hibernate para
mantener tu c&#x00f3;digo portable.
</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>
<emphasis>Ligamento Autom&#x00e1;tico JNDI</emphasis>: Hibernate puede ligar sus
<literal>SessionFactory</literal> a JNDI despu&#x00e9;s del arranque.
</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>
<emphasis>Ligamento de Sesi&#x00f3;n JTA:</emphasis>
La <literal>Session</literal> de Hibernate puede ser ligada autom&#x00e1;ticamente
al &#x00e1;mbito de transacciones JTA si usas EJBs. Simplemente busca la
<literal>SessionFactory</literal> de JNDI y obt&#x00e9;n la <literal>Session</literal>
actual. Deja que Hibernate cuide de limpiar y cerrar la <literal>Session</literal>
cuando se complete tu transacci&#x00f3;n JTA. La demarcaci&#x00f3;n de transacci&#x00f3;n
es declarativa, en descriptores de despliegue de EJB.
</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>
<emphasis>Despliegue JMX:</emphasis> Si tienes un servidor de aplicaciones capaz
de JMX (por ejemplo, JBoss AS), puedes optar por desplegar Hibernate como un MBean
manejado. Esto te ahorra el c&#x00f3;digo de una l&#x00ed;nea de arranque para
construir tu <literal>SessionFactory</literal> desde una <literal>Configuration</literal>.
El contenedor arrancar&#x00e1; tu <literal>HibernateService</literal>, e idealmente tambi&#x00e9;n
cuidar&#x00e1; de las dependencias entre servicios (El datasource debe estar
disponible antes que arranque Hibernate, etc).
</para>
</listitem>
</itemizedlist>
<para>
Dependiendo de tu entorno, podr&#x00ed;as tener que establecer la opci&#x00f3;n
de configuraci&#x00f3;n <literal>hibernate.connection.aggressive_release</literal>
a true si tu servidor de aplicaciones muestra excepciones "connection containment".
</para>
<sect2 id="configuration-optional-transactionstrategy" revision="3">
<title>Configuraci&#x00f3;n de la estrategia de transacci&#x00f3;n</title>
<para>
La API de <literal>Session</literal> de Hibernate es independiente de cualquier
demarcaci&#x00f3;n de transacci&#x00f3;n en tu arquitectura. Si dejas que Hibernate
use JDBC directamente, a trav&#x00e9;s de un pool de conexiones. puedes comenzar y
acabar tus transacciones llamando la API de JDBC. Si ejecutas en un servidor de
aplicaciones J2EE, podr&#x00e9;as querer usar transacciones manejadas por bean y
llamar la API de JTA y <literal>UserTransaction</literal> cuando sea necesario.
</para>
<para>
Para mantener tu c&#x00f3;digo portable entre estos dos (y otros) entornos recomendamos la API
de <literal>Transaction</literal> de Hibernate, que envuelve y oculta el sistema subyacente.
Tienes que especificar una clase f&#x00e1;brica para las instancias de <literal>Transaction</literal>
estableciendo la propiedad de configuraci&#x00f3;n <literal>hibernate.transaction.factory_class</literal>
de Hibernate.
</para>
<para>
Hay tres elecciones est&#x00e1;ndar (prefabricadas):
</para>
<variablelist spacing="compact">
<varlistentry>
<term><literal>org.hibernate.transaction.JDBCTransactionFactory</literal></term>
<listitem>
<para>delega a transacciones de base de datos (JDBC) (por defecto)</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>org.hibernate.transaction.JTATransactionFactory</literal></term>
<listitem>
<para>
delega a transacciones manejadas por contenedor si una transacci&#x00f3;n
existente est&#x00f3; por debajo en este contexto (ej. m&#x00e9;todo de un
bean de sesi&#x00f3;n EJB), en otro caso una nueva transacci&#x00f3;n es
comenzada y se usan transacciones manejadas por bean.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>org.hibernate.transaction.CMTTransactionFactory</literal></term>
<listitem>
<para>delega a transacciones JTA manejadas por contenedor</para>
</listitem>
</varlistentry>
</variablelist>
<para>
Puedes definir tambi&#x00e9;n tus propias estrategias de transacci&#x00f3;n
(para un servicio de transacci&#x00f3;n CORBA, por ejemplo).
</para>
<para>
Algunas funcionalidades en Hibernate (ej, el cach&#x00e9; de segundo nivel, ligamento
autom&#x00e1;tico de JTA y Session, etc.) requieren acceso al <literal>TransactionManager</literal>
de JTA en un entorno manejado. En un servidor de aplicaciones tienes que especificar
c&#x00f3;mo Hibernate debe obtener una referencia al <literal>TransactionManager</literal>,
pues J2EE no estandariza un solo mecanismo:
</para>
<table frame="topbot" id="jtamanagerlookup" revision="1">
<title>TransactionManagers de JTA</title>
<tgroup cols="2">
<colspec colwidth="2.5*"/>
<colspec colwidth="1*"/>
<thead>
<row>
<entry>Transaction Factory</entry>
<entry align="center">Servidor de Aplicaciones</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>org.hibernate.transaction.JBossTransactionManagerLookup</literal></entry>
<entry align="center">JBoss</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction.WeblogicTransactionManagerLookup</literal></entry>
<entry align="center">Weblogic</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction.WebSphereTransactionManagerLookup</literal></entry>
<entry align="center">WebSphere</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</literal></entry>
<entry align="center">WebSphere 6</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction.OrionTransactionManagerLookup</literal></entry>
<entry align="center">Orion</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction.ResinTransactionManagerLookup</literal></entry>
<entry align="center">Resin</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction.JOTMTransactionManagerLookup</literal></entry>
<entry align="center">JOTM</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction.JOnASTransactionManagerLookup</literal></entry>
<entry align="center">JOnAS</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction.JRun4TransactionManagerLookup</literal></entry>
<entry align="center">JRun4</entry>
</row>
<row>
<entry><literal>org.hibernate.transaction.BESTransactionManagerLookup</literal></entry>
<entry align="center">Borland ES</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<sect2 id="configuration-optional-jndi" revision="2">
<title><literal>SessionFactory</literal> ligada a JNDI</title>
<para>
Una <literal>SessionFactory</literal> de Hibernate ligada a JNDI puede simplificar
la obtenci&#x00f3;n de la f&#x00e1;brica y la creaci&#x00f3;n de nuevas
<literal>Session</literal>s. Observa que esto no est&#x00e1; relacionado a un
<literal>Datasource</literal> ligado a JNDI, simplemente ambos usan el mismo
registro!
</para>
<para>
Si deseas tener la <literal>SessionFactory</literal> ligada a un espacio de nombres de JNDI,
especifica un nombre (ej. <literal>java:hibernate/SessionFactory</literal>) usando la
propiedad <literal>hibernate.session_factory_name</literal>. Si esta propiedad es omitida,
la <literal>SessionFactory</literal> no ser&#x00e1; ligada a JNDI (Esto es especialmente
&#x00fa;til en entornos con una implementaci&#x00f3; JNDI de s&#x00f3;lo lectura por defecto,
ej. Tomcat.)
</para>
<para>
Al ligar la <literal>SessionFactory</literal> a JNDI, Hibernate usar&#x00e1; los valores de
<literal>hibernate.jndi.url</literal>, <literal>hibernate.jndi.class</literal> para instanciar
un contexto inicial. Si &#x00e9;tos no se especifican, se usar&#x00e1; el
<literal>InitialContext</literal> por defecto.
</para>
<para>
Hibernate colocar&#x00e1; autom&#x00e1;ticamente la <literal>SessionFactory</literal>
en JNDI despu&#x00e9;s que llames a <literal>cfg.buildSessionFactory()</literal>.
Esto significa que tendr&#x00e1;s al menos esta llamada en alg&#x00fa;n c&#x00f3;digo
de arranque (o clase de utilidad) en tu aplicaci&#x00f3;n, a menos qie uses el despliegue
JMX con el <literal>HibernateService</literal> (discutido luego).
</para>
<para>
Si usas una <literal>SessionFactory</literal> de JNDI, un EJB o cualquier otra
clase puede obtener la <literal>SessionFactory</literal> usando una b&#x00fa;squeda
JNDI. Observa que esta configuraci&#x00f3;n no es necesaria si usas la clase de ayuda
<literal>HibernateUtil</literal> introducida en el cap&#x00ed;tulo uno, que act&#x00fa;a
como un registro Singleton. Sin embargo, <literal>HibernateUtil</literal> es m&#x00e1;s
com&#x00fa;n en un entorno no manejado.
</para>
</sect2>
<sect2 id="configuration-j2ee-currentsession" revision="1">
<title>Ligado autom&#x00e1;tico de JTA y Session</title>
<para>
Para entornos no manejados hemos sugerido <literal>HibernateUtil</literal> con una
<literal>SessionFactory</literal> est&#x00e1;tica, y administraci&#x00f3;n de la
<literal>Session</literal> de Hibernate. Este enfoque no es f&#x00e1;cil de usar
en un entorno EJB, al poder ejecutarse muchos EJBs dentro de la misma transacci&#x00f3;n
pero no en la misma hebra. Recomendados que ligues la <literal>SessionFactory</literal>
a JNDI en un entorno manejado.
</para>
<para>
En vez de rodar tu propia utilidad de <literal>ThreadLocal</literal>,
usa el m&#x00e9;todo <literal>getCurrentSession()</literal> en la
<literal>SessionFactory</literal> para obtener una <literal>Session</literal>
de Hibernate. Si no hubiese una <literal>Session</literal> de Hibernate en la
transacci&#x00f3;n JTA actual, se arrancar&#x00e1; y asignar&#x00e1; una.
Ambas opciones de configuraci&#x00f3;n <literal>hibernate.transaction.flush_before_completion</literal>
y <literal>hibernate.transaction.auto_close_session</literal>, ser&#x00e1;n establecidas
autom&#x00e1;ticamente para cada <literal>Session</literal> que obtengas con
<literal>getCurrentSession()</literal>, de modo que &#x00e9;stas ser&#x00e1;n
limpiadas (flushed) y cerradas autom&#x00e1;ticamente cuando el contenedor complete
las transacciones JTA.
</para>
<para>
Si tu, por ejemplo, usas el patr&#x00f3;n de dise&#x00f1;o DAO para escribir tu
capa de persistencia, todos los DAO's buscan la <literal>SessionFactory</literal>
cuando se necesite y abren la sesi&#x00f3;n "actual". No hay necesidad de pasar
las instancias de <literal>SessionFactory</literal> o <literal>Session</literal>
alrededor entre el c&#x00f3;digo de control y el c&#x00f3;digo DAO.
</para>
</sect2>
<sect2 id="configuration-j2ee-jmx" revision="1">
<title>Despliegue JMX</title>
<para>
La l&#x00ed;nea <literal>cfg.buildSessionFactory()</literal> todav&#x00ed;a tiene
que ser ejecutada en algun sitio para obtener una <literal>SessionFactory</literal>
en JNDI. Puedes hacer esto bien en un bloque inicializador <literal>static</literal>
(como aquel en <literal>HibernateUtil</literal>) o bien despliegas Hibernate como un
<emphasis>servicio manejado</emphasis>.
</para>
<para>
Hibernate se distribuye con <literal>org.hibernate.jmx.HibernateService</literal>
para despliegue en un servidor de aplicaciones con capacidades JMX, como JBoss AS.
El despliegue y la configurac&#x00f3;n reales son espec&#x00ed;ficos del vendedor.
He aqu&#x00ed; un <literal>jboss-service.xml</literal> de ejemplo para JBoss 4.0.x:
</para>
<programlisting><![CDATA[<?xml version="1.0"?>
<server>
<mbean code="org.hibernate.jmx.HibernateService"
name="jboss.jca:service=HibernateFactory,name=HibernateFactory">
<!-- Required services -->
<depends>jboss.jca:service=RARDeployer</depends>
<depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends>
<!-- Bind the Hibernate service to JNDI -->
<attribute name="JndiName">java:/hibernate/SessionFactory</attribute>
<!-- Datasource settings -->
<attribute name="Datasource">java:HsqlDS</attribute>
<attribute name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>
<!-- Transaction integration -->
<attribute name="TransactionStrategy">
org.hibernate.transaction.JTATransactionFactory</attribute>
<attribute name="TransactionManagerLookupStrategy">
org.hibernate.transaction.JBossTransactionManagerLookup</attribute>
<attribute name="FlushBeforeCompletionEnabled">true</attribute>
<attribute name="AutoCloseSessionEnabled">true</attribute>
<!-- Fetching options -->
<attribute name="MaximumFetchDepth">5</attribute>
<!-- Second-level caching -->
<attribute name="SecondLevelCacheEnabled">true</attribute>
<attribute name="CacheProviderClass">org.hibernate.cache.EhCacheProvider</attribute>
<attribute name="QueryCacheEnabled">true</attribute>
<!-- Logging -->
<attribute name="ShowSqlEnabled">true</attribute>
<!-- Mapping files -->
<attribute name="MapResources">auction/Item.hbm.xml,auction/Category.hbm.xml</attribute>
</mbean>
</server>]]></programlisting>
<para>
Este fichero es desplegado en un directorio llamado <literal>META-INF</literal> y
empaquetado en un fichero JAR con la extensi&#x00f3;n <literal>.sar</literal>
(fichero de servicio). Tambi&#x00e9;n necesitas empaquetar Hibernate, sus bibliotecas
de terceros requeridas, tus clases persistentes compiladas, as&#x00ed; como tus ficheros de mapeo
en el mismo fichero. Tus beans de empresa (usualmente beans de sesi&#x00f3;n) pueden ser
mantenidos en su propio fichero JAR, pero debes incluir este fichero EJB JAR en el fichero
de servicio principal para obtener una unidad desplegable (en caliente). Consulta la documentaci&#x00f3;n
de JBoss AS para m&#x00e1;s informaci&#x00f3;n sobre el servicio JMX y despliegue de EJB.
</para>
</sect2>
</sect1>
</chapter>