====== Usando Hibernate ====== Hasta ahora hemos visto cómo configurar hibernate usando los ficheros XML de configuración o usando notaciones pero no hemos visto nada de código Java para usarlo realmente. En esta lección veremos finalmente cómo usar Java para persistir una clase. La clase que más usaremos en Hibernate es org.hibernate.Session. Esta clase contiene métodos para leer, guardar o borrar entidades sobre la base de datos. Pero antes de poder usarla hace falta crear el objeto org.hibernate.SessionFactory|SessionFactory que mediante el método org.hibernate.SessionFactory#openSession()|SessionFactory.openSession() nos dará acceso a org.hibernate.Session|Session. Session session = sessionFactory.openSession(); Veamos ahora cómo crear el objeto org.hibernate.SessionFactory|SessionFactory. ===== SesionFactory ===== La forma de crear el objeto org.hibernate.SessionFactory|SessionFactory es mediante un objeto org.hibernate.cfg.Configuration que leerá el fichero de configuración de hibernate ''hibernate.cfg.xml'' que se encuentra en el directorio raíz de las clases Java. import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; SessionFactory sessionFactory; Configuration configuration = new Configuration(); configuration.configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); * En la línea 8 vemos cómo se crea el objeto org.hibernate.cfg.Configuration|Configuration * En la línea 9 mediante el método org.hibernate.cfg.Configuration#configure()|configure() se va a leer el fichero de configuración ''hibernate.cfg.xml''. * La línea 10 es nueva en hibernate 4 y contiene la lista de los distintos servicios que usará (( Tiene registrados)) hibernate.Para ello se crea un objeto de la clase org.hibernate.service.ServiceRegistry. * La línea 11 es la que finalmente creará el objeto org.hibernate.SessionFactory|SessionFactory en función de la configuración y de los servicios. Todo el código anterior deberá realizarse una única vez en la aplicación y deberemos guardar la referencia a org.hibernate.SessionFactory|SessionFactory para su posterior uso durante toda la vida de la aplicación. Si vemos la [[http://docs.jboss.org/hibernate/orm/4.1/quickstart/en-US/html_single/#hibernate-gsg-tutorial-basic-test|documentación de hibernate 4.1]] se indica que la forma de crear el objeto org.hibernate.SessionFactory|SessionFactory es la siguiente: Configuration configuration = new Configuration(); configuration.configure(); sessionFactory = configuration.buildSessionFactory(); Sin embargo al usar este código se puede observar que el método org.hibernate.cfg.Configuration#buildSessionFactory()|buildSessionFactory() está depreciado.En la documentación del propio método se indica que ahora se use org.hibernate.cfg.Configuration#buildSessionFactory(org.hibernate.service.ServiceRegistry)|buildSessionFactory(ServiceRegistry serviceRegistry) es decir que la documentación contiene un error y debemos usar el código del Listado 1. Una discusión sobre el error en la documentación de Hibernate 4 la podéis encontrar en:[[http://stackoverflow.com/questions/8621906/is-buildsessionfactory-deprecated-in-hibernate-4|Is buildSessionFactory() deprecated in hibernate 4?]] Al finalizar la aplicación deberemos llamar al método org.hibernate.SessionFactory#close()|close(): sessionFactory.close(); ===== Session ===== Ahora que ya tenemos el objeto org.hibernate.SessionFactory|SessionFactory podemos obtener la org.hibernate.Session|Session para trabajar con Hibernate. Como ya hemos visto crear la org.hibernate.Session|Session es tan sencillo como llamar al método org.hibernate.SessionFactory#openSession()|openSession(): Session session = sessionFactory.openSession(); Una vez obtenida la sesión trabajaremos con Hibernate persistiendo las clases y una vez finalizado se deberá cerrar la sesión con el método org.hibernate.Session#close()|close(): session.close(); ===== Transacciones ===== Para trabajar con una base de datos usamos las transacciones. En hibernate es tan sencillo como: * Crear una nueva transacción llamando al método org.hibernate.SharedSessionContract#beginTransaction()|beginTransaction() de la sesión: session.beginTransaction(); \\ * Hacer un commit de la transacción actual llamando al método org.hibernate.Transaction#commit()|commit() de la transacción actual de la sesión: session.getTransaction().commit(); \\ * Hacer un rollback de la transacción actual llamando al método org.hibernate.Transaction#rollback()|rollback() de la transacción actual de la sesión: session.getTransaction().rollback(); ===== CRUD ===== Ya hemos llegado al punto en que tenemos todo preparado para poder trabajar con Hibernate en las operaciones fundamentales de una base de datos, las operaciones [[wpes>CRUD]]. * **C**reate: Guardar un nuevo objeto en la base de datos. * **R**ead:Leer los datos de un objeto de la base de datos. * **U**pdate:Actualizar los datos de un objeto de la base de datos. * **D**elete:Borrar los datos de un objeto de la base de datos. Estas 4 operaciones será tan sencillas de usar desde hibernate como llamar a un único método para cada uno de ellos. ==== Guardar ==== Usaremos el método org.hibernate.Session#save(java.lang.Object)|save(Object object) de la sesión pasándole como argumento el objeto a guardar. Profesor profesor=new Profesor(101, "Juan", "Perez", "García"); //Creamos el objeto Session session = sessionFactory.openSession(); session.beginTransaction(); session.save(profesor); //<|--- Aqui guardamos el objeto en la base de datos. session.getTransaction().commit(); session.close(); Como vemos , guardar una clase Java en la base de datos solo implica usar una única línea. ==== Leer ==== El método que debemos usar es org.hibernate.Session#get(java.lang.Class, java.io.Serializable)|get(Class,Serializable), al que le deberemos pasar la clase que queremos leer y su clave primaria. Profesor profesor=(Profesor)session.get(profesor.class,101); El método org.hibernate.Session#get(java.lang.Class, java.io.Serializable)|get(Class,Serializable) permite leer un único objeto de la base de datos a partir de su clave primaria. El uso de este método tiene 2 peculiaridades: * Uso del cast:Es necesario hacer un cast añadiendo ''(Message)'' en el retorno de la función. Ésto es así ya que el método org.hibernate.Session.html#get(java.lang.Class, java.io.Serializable)|get() se usa para cualquier tipo de entidad así que Java desconoce que tipo de datos va a retornar , por lo que debemos decírselo nosotros mediante el cast para "asegurarle" el tipo que retorna. * El uso de la propiedad ''.class'':Ésta es la forma que se ha definido en en lenguaje Java para pasar un objeto de la clase java.lang.Class. Véase [[http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.8.2|Class Literals]]. ==== Actualizar ==== El método a usar es org.hibernate.Session#update(java.lang.Object)|update(Object object), al que le deberemos pasar el objeto a actualizar en la base de datos session.beginTransaction(); session.update(profesor); session.getTransaction().commit(); El método org.hibernate.Session#update(java.lang.Object)|update(Object object) simplemente actualiza el objeto de la base de datos. ==== Borrar ==== Ahora pasemos a borrar un objeto desde la base de datos.El método que debemos usar es org.hibernate.Session#delete(java.lang.Object)|delete(Object object), al que le deberemos pasar el objeto a borrar de la base de datos session.beginTransaction(); session.delete(profesor); session.getTransaction().commit(); El método org.hibernate.Session#delete(java.lang.Object)|delete(Object object) simplemente borra el objeto de la base de datos. ==== Guardar y actualizar ==== Muchas veces resulta cómodo al programar no tener que estar pendiente de si un objeto va a insertarse o actualizarse. Para ello Hibernate dispone del método org.hibernate.Session#saveOrUpdate(java.lang.Object)|saveOrUpdate(Object object) que inserta o actualiza en la base de datos en función de si ya existe o no dicha fila. Profesor profesor=new Profesor(101, "Juan", "Perez", "García"); session.beginTransaction(); session.saveOrUpdate(profesor); session.getTransaction().commit(); En este caso dependiendo de si existe o no la fila en la base de datos con ''Id=101'' se realizará un ''UPDATE'' o un ''INSERT'' contra la base de datos. ===== Referencias ===== * [[http://stackoverflow.com/questions/8621906/is-buildsessionfactory-deprecated-in-hibernate-4|Is buildSessionFactory() deprecated in hibernate 4?]]: Discusión sobre el error en la documentación de Hibernate 4. * [[http://rgordon.co.uk/blog/2012/02/24/hibernate-please-dont-deprecate-yourself/|Hibernate – Please Don’t Deprecate Yourself]]: Post sobre la nueva forma de crear el buildSessionFactory en Hibernate 4. * [[http://docs.jboss.org/hibernate/orm/4.1/quickstart/en-US/html_single/#hibernate-gsg-tutorial-basic-test|Documentación de hibernate 4.1]]:Documentación errónea sobre crear el objeto org.hibernate.SessionFactory|SessionFactory.