Clases Persistentes Clases presistentes son clases en una aplicación que implementan las entidades del problema de negocio (por ejemplo, Customer y Order en una aplicación de comercio electrónico). No todas las instancias de una clase persistente se considera que estén en el estado persistente, una instancia puede en cambio ser transitoria o estar separada. Hibernate funciona mejor si las clases siguen algunas simples reglas, también conocidas como el modelo de programación de Viejas Clases Java Planas (Plain Old Java Object o POJO). Sin embargo, ninguna de estas reglas son requerimientos rígidos. En cambio, Hibernate3 asume muy poco acerca de la naturaleza de tus objetos persistentes. Puedes expresar un modelo de dominio en otras formas: usando árboles de instancias de Map, por ejemplo. Un ejemplo simple de POJO La mayoría de aplicaciones Java requieren una clase representando felinos. Aquí hay cuatro reglas principales a seguir: Implementa un constructor sin argumentos Cat tiene un contructor sin argumentos. Todas las clases persistentes deben tener un constructor por defecto (que puede no ser público) de modo que Hibernate pueda instanciarlas usando Constructor.newInstance(). Recomendamos fuertemente tener un constructor por defecto con al menos visibilidad de package para la generación de proxies en tiempo de ejecución en Hibernate. Provee una propiedad identificadora (opcional) Cat tiene una propiedad llamada id. Esta propiedad mapea a la columna clave primaria de la tabla de base de datos. La propiedad podría llamarse cualquierCosa, y su tipo podría haber sido cualquier tipo primitivo, cualquier tipo de "envoltura" primitivo, java.lang.String o java.util.Date. (Si tu tabla de base de datos heredada tiene claves compuestas, puedes incluso usar una clase definida por el usuario con propiedades de estos tipos, ver la sección sobre identificadores compuestos luego.) La propiedad identificadora es estrictamente opcional. Puedes olvidarla y dejar que Hibernate siga internamente la pista de los identificadores del objeto. Sin embargo, no recomendamos esto. De hecho, alguna funcionalidad está disponible sólo para clases que declaran una propiedad identificadora: Reasociación transitiva de objetos separados (actualizaciones o fusiones en cascada) - ver Session.saveOrUpdate() Session.merge() Recomendamos que declares propiedades identificadoras nombradas-consistentemente en clases persistentes. Mas aún, recomendamos que uses un tipo nulable (es decir, no primitivo). Prefiere las clases no finales (opcional) Un aspecto central de Hibernate, proxies, depende de que las clases persistentes sean ya no finales, o sean ya la implementación de una interface que declare todos los métodos públicos. Puedes persistir con Hibernate clases final que no implementen una interface, pero no serás capaz de usar proxies para recuperación perezosa de asociaciones, lo que limitará tus opciones para afinar el rendimiento. Debes también evitar declarar métodos public final en clases non-final. Si quieres usar una clase con un método public final, debes deshabilitar explícitamente el uso de proxies estableciendo lazy="false". Declara métodos de acceso y modificación para los campos persistentes (opcional) Cat declara métodos de acceso para todos sus campos persistente. Muchas otras herramientas ORM persisten directamente variables de instancia. Creemos que es mejor proveer una indirección entre el esquema relacional y las estructuras internas de la clase. Por defecto, Hibernate persiste propiedades del estilo JavaBeans, y reconoce nombres de método de la forma getFoo, isFoo y setFoo. Puedes cambiar a acceso directo a campos para propiedades en particular, de ser necesario. Las propiedades no necesitan ser declaradas públicas. Hibernate puede persistir una propiedad con un par get / set protected o private. Implementando herencia Una subclase puede a su vez observar la primera y segunda regla. Hereda su propiedad identificadora de la superclase, Cat. Implementando <literal>equals()</literal> y <literal>hashCode()</literal> Tienes que sobrescribir los métodos equals() y hashCode() si : piensas poner instancias de clases persistentes en un Set (la forma recomendada de representar asociaciones multivaluadas) y piensas usar reasociación de instancias separadas. Hibernate garantiza la equivalencia de identidad persistente (fila de base de datos) y identidad Java sólo dentro del ámbito de una sesión en particular. De modo que en el momento que mezclamos instancias recuperadas en sesiones diferentes, debemos implementar equals() y hashCode() si deseamos tener una semántica significativa de Sets. La forma más obvia es implementar equals()/hashCode() comparando el valor identificador de ambos objetos. Si el valor es el mismo, ambos deben ser la misma fila de base de datos, por lo tanto son iguales (si ambos son agregados a un Set, sólo tendremos un elemento en el Set). Desafortunadamente, no podemos usar este enfoque con identificadores generados! Hibernate sólo asignará valores identificadores a objetos que son persistentes, una instancia recién creada no tendrá ningún valor identificador! Además, si una instancia no está salvada y está actualmente en un Set, salvarla asignará un valor identificador al objeto. Si equals() and hashCode() están basados en el valor identificador, el código hash podría cambiar, rompiendo el contrato de Set. Ver el sitio web de Hibernate para una discusión completa de este problema. Observa que esto no es una incidencia de Hibernate, sino la semántica normal de Java de identidad de objeto e igualdad. Recomendamos implementar equals() y hashCode() usando igualdad de clave de negocio (Business key equality). Igualdad de clave de negocio significa que el método equals() compara sólo las propiedades que forman la clave de negocio, una clave que podría identificar nuestra instancia en el mundo real (una clave candidata natural): Nota que una clave de negocio no tiene que ser tan sólida como una clave primaria candidata de base de datos (ver ). Las propiedades inmutables o únicas son usualmente buenas candidatas para una clave de negocio. Modelos dinámicos Ten en cuenta que las siguientes funcionalidades están consideradas actualmente experimentales y pueden cambiar en el futuro cercano. Las entidades persistentes no necesariamente tienen que estar representadas como clases POJO o como objetos JavaBean en tiempo de ejecución. Hibernate soporta además modelos dinámicos (usando Maps de Maps en tiempo de ejecución) y la representación de entidades como árboles de DOM4J. Con este enfoque no escribes clases persistentes, sólo ficheros de mapeo. Por defecto, Hibernate funciona en modo POJO normal. Puedes establecer una representación de entidad por defecto para una SessionFactory en particular usando la opción de configuración default_entity_mode (ver ). Los siguientes ejemplos demuestran la representación usando Maps. Primero, en el fichero de mapeo, tiene que declararse un entity-name en vez de (o como agregado a) un nombre de clase: ]]> Ten en cuenta que aunque las asociaciones se declaran usando nombres de clase objetivo, el tipo objetivo de una asociación puede ser además una entidad dinámica en vez de un POJO. Después de establecer el modo de entidad por defecto a dynamic-map para la SessionFactory, podemos trabajar en tiempo de ejecución con Maps de Maps: Las ventajas de un mapeo dinámico es rápido tiempo de ciclo de prototipado sin la necesidad de implementación de clases de entidad. Sin embargo, pierdes chequeo de tipos en tiempo de compilación y muy probablemente tratarás con muchas excepciones en tiempo de ejecución. Gracias al mapeo de Hibernate, el esquema de base de datos puede estar facilmente sano y normalizado, permitiendo agregar una implementación apropiada del modelo de dominio más tarde. Los modos de representación de entidad pueden ser establecidos por Session: Por favor, ten en cuenta que la llamada a getSession() usando un EntityMode está en la API de Session, no en la de SessionFactory. De esta forma, la nueva Session comparte la conexión JDBC, transacción y otra información de contexto. Esto significa que no tienes que llamar a flush() ni a close() en la Session secundaria, y tembién dejar el manejo de la transacción y de la conexión a la unidad de trabajo primaria. Puede encontrarse más información sobre las capacidades de representación XML en . PORHACER: Documentar el framework de extensiones del usuario en los paquetes de propiedad y proxies.