Obtener y liberar la sesión desde HibernateDaoSupport

Buenas tardes a todos, una gran pregunta:
Alguien de ustedes sabe cuál es la forma correcta de obtener la sesión desde una clase que extiende de HibernateDaoSupport?
Yo lo hago con el siguiente código, sin embargo siento por alguna causa que no es correcto, no se si sea correcto ese releaseSession y si tenga que obtener la sesión del SessionFactory

        Session session = null;
        List list = null;

        try {
            session = getSession();
            ...
        } finally {
            releaseSession(session);
        }

Gracias de antemano

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

interceptor

No prefieres usar el HibernateInterceptor? con eso tu código no está tan acoplado a Spring, porque el interceptor lo pegas en la configuración (en el application context) y se encarga de cerrar todas las sesiones y de darte una sesión previamente abierta si pides una, o crearla si no hay una... y así tu DAO no tiene que extender ninguna clase en particular, solamente implementar una interfaz (porque el interceptor creará un proxy dinámico que envuelve tu DAO).

La documentación del HibernateDaoSupport indica que la idea es que lo uses con un HibernateTemplate, y los métodos que indicas son solamente para sesiones transaccionales. Pero supongo que para transacciones puedes simplemente anotar los métodos y usar la transaccionalidad por configuración de Spring.

Regresando a lo del interceptor... un ejemplo:

Esta es la configuración de los DAOs de JavaMexico 2.0 con Hibernate y Spring. El interceptor de Hibernate está definido hasta abajo. Si ves cualquier DAO, es un proxy que envuelve el componente real y se le indica la interfaz que implementa el mismo. Por ejemplo el DAO de usuario implementa esta interfaz y si ves la implementación, es un POJO que sólo implementa esa interfaz. También notarás que ningún método cierra la sesión que obtiene, precisamente porque el interceptor se encargará de eso. Si tuvieras por ejemplo un DAO en donde un método1 invoca un método2, lo que pasa en runtime es:

1. Tienes un componente que tiene inyectado tu DAO, pero la referencia es a la interfaz, no a la implementación (eso es crucial).
2. Invocas dao.metodo1() desde ese componente. La referencia que tienes es realmente al proxy, no al DAO directamente, por lo que el proxy intercepta la llamada, hace algunas cosillas y luego invoca el metodo1() de tu DAO.
3. En tu DAO pides una sesión a la SessionFactory. Como no existe una sesión, la crea y pues lleva la cuenta de que existe (guarda esa referencia para el proxy).
4. El metodo1 del DAO invoca metodo2(). Ahí no se da cuenta el proxy porque ya es una llamada interna, pero no importa; cuando en metodo2 se le pide una sesión a la SessionFactory, ésta devuelve la que ya fue creada en metodo1 y se usa la misma.
5. Termina de ejecutarse metodo2, regresa el control a metodo1, termina su ejecución sin tener que cerrar sesiones.
6. Regresa el control al proxy, que por medio del interceptor, cierra la sesión que fue abierta antes de darle el control a metodo1.

Así que el interceptor se encarga de crear y cerrar las sesiones conforme se necesiten, con lo que tu código ya no tiene que estar lleno de try-finally.

HibernateInterceptor con anotaciones Spring

Busco y busco ejemplos pero no encuentro cómo se implementa esto cuando utilizo anotaciones, todo lo tengo marcado con anotaciones @Transactional y en ningún momento estoy utilizando de manera explicita "ProxyFactoryBean", no entiendo cómo es que mi aplicación está interceptando las transacciones :S , menudo problema en el que me encuentro

Podrías orientarme cómo implementar HibernateInterceptor cuando utilizo anotaciones?

springContext.xml:

...
<context:annotation-config />

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

Imagen de ezamudio

dos cosas distintas

Las transacciones ya las tienes implementadas porque anotas tus componentes con @Transactional y pusiste en tu application context el <tx:annotation-driven/>, es todo lo que necesitas; con eso todos los beans que pongas en el application context y que tengan la anotación @Transactional (en la clase o en los métodos) utilizarán transacciones.

Para el HibernateInterceptor ya te dejé varias ligas que te llevan a fuentes de javaMexico 2.0 para que veas cómo lo implementamos ahí.

Si, gracias. Perdón si soy

Si, gracias.
Perdón si soy insistente pero tengo dudas que no encuentro, no soy de los que pregunta sin antes buscar

Mi duda es si yo podía sustituir su código:

<bean id="usuarioDao" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="frozen" value="true" />
        <property name="proxyInterfaces" value="org.javamexico.dao.UserDao" />
        <property name="target"><bean class="org.javamexico.dao.hib3.UsuarioDAO">
                <property name="sessionFactory" ref="hibFactory" />
        </bean></property>
        <property name="interceptorNames"><list>
                <value>hibInterceptor</value>
        </list></property>
</bean>

con anotaciones, para evitar estar definiendo en archivos xml. Gracias por su tiempo y su sabiduría ezamudio !

Imagen de ezamudio

NPI

revisa los docs de spring, que estan bastante completos. Lo que buscas es annotation-based configuration, no se si haya algo para lo de hibernate con interceptores.

Gracias

Gracias, buscando... ;)

HibernateInterceptor

Joven ezamudio:

Agradezco mucho sus palabras de ayuda y por guiarme por dónde debía buscar, he investigado el tema y he revisado su código del proyecto JM2.0... Muy interesante la forma en la que usted plasma lo que dice en el código.
Luego de buscar encontré que HibernateInterceptor es una alternativa al patrón OpenSessionInView y entre tantas curiosidades también encontré que el patrón OSIV (OpenSessionInView) se considera una mala práctica de programación, ¿sabe usted porqué, podría usted compartir sus experiencias? Veo que no implementó ese patrón en JM2.0 y en lugar de ello utilizó HibernateInterceptor

Gracias

Imagen de ezamudio

acoplamiento

El patrón OSIV aumenta el acoplamiento, porque entonces la vista requiere tener una sesión de hibernate abierta, lo que implica que la vista ya "sabe" que estás usando hibernate, cuando realmente la vista debería de poder funcionar sin tener que saber nada de Hibernate. Si implementas OSIV, luego puedes tener problemas si se decide que la aplicación debe separarse físicamente la vista del modelo y los DAOs en la vista realmente son proxies RMI o alguna otra variante para conectarse a los DAOs como servicios remotos.

Además, ya que empiezas con OSIV luego empiezas a modificar el modelo y tus clases de dominio para acomodar cosas que sólo sirven para la vista.

Gracias

Ahora entiendo, muchas gracias por compartir ezamudio