Hibernate / Spring: getHibernateTemplate (). Save (…) Se congela / cuelga

Estoy usando Hibernate y Spring con el patrón DAO (todas las dependencias de Hibernate en una clase * DAO.java). Tengo nueve pruebas unitarias (JUnit) que crean algunos objetos comerciales, los guardan y realizan operaciones en ellos; los objetos están en un hash (por lo que estoy reutilizando los mismos objetos todo el tiempo).

Mi método de configuración de JUnit llama a mi DAO.deleteAllObjects() método que llama getSession().createSQLQuery("DELETE FROM <tablename>").executeUpdate() para mi tabla de objetos de negocio (solo uno).

Una de mis pruebas unitarias (# 8/9) se congela. Supuse que era un punto muerto en la base de datos, porque el archivo de registro de Hibernate muestra mi declaración de eliminación en último lugar. Sin embargo, la depuración mostró que es simplemente HibernateTemplate.save(someObject) eso está helando. (Eclipse muestra que se está congelando HibernateTemplate.save(Object), línea 694.)

También es interesante notar que ejecutar esta prueba por sí sola (no en el conjunto de 9 pruebas) no causa ningún problema.

¿Cómo diablos soluciono problemas y soluciono esto?

Además, estoy usando @Entity anotaciones, si eso importa.

Edit: Eliminé la reutilización de mis objetos comerciales (uso objetos únicos en cada método), no marcó la diferencia (todavía se congela).

Edit: Esto también comenzó a filtrarse en otras pruebas (no se puede ejecutar más de una clase de prueba sin que algo se congele)

Edit: Dividir las pruebas de congelación en dos clases funciona. Voy a hacer eso por ahora, tan vergonzosamente no SECO como es tener dos o más clases de prueba probando unitariamente la misma clase de objeto de negocio.

Configuración de la transacción:

    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- the transactional semantics... -->
        <tx:attributes>
            <!-- all methods starting with 'get' are read-only -->
            <tx:method name="get*" read-only="true" />
            <tx:method name="find*" read-only="true" />
            <!-- other methods use the default transaction settings (see below) -->
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>

    <!-- my bean which is exhibiting the hanging behavior -->
    <aop:config>
    <aop:pointcut id="beanNameHere"
        expression="execution(* com.blah.blah.IMyDAO.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="beanNameHere" />
</aop:config>

preguntado el 08 de enero de 11 a las 17:01

¿Está realizando transacciones después de cada método de prueba? -

Soy un n00b hibernate (más experimentado con NHibernate - casi no se requiere ninguna configuración), así que voy a plantear la hipótesis de que sí, lo soy. Edité mi respuesta para incluir alguna configuración transaccional. También intenté llamar a session.flush () y transaction.flush (), sin éxito. -

2 Respuestas

Cuando se congele, rompa la aplicación, busque el hilo principal y capture el seguimiento de la pila. Examine hasta que encuentre exactamente qué consulta de base de datos se está ejecutando y está bloqueando en la base de datos.

Mencionas que ejecutar la prueba por sí solo funciona bien, pero ejecutar el conjunto completo causa un problema. Si este es el caso, supongo que una de las pruebas anteriores todavía tiene una transacción abierta y tiene bloqueos en algunas filas a las que la prueba de bloqueo está intentando acceder.

¿Sus pruebas se ejecutan al mismo tiempo? Si es así, deje de hacer eso, ya que podrían interferir entre sí.

Active la opción hibernate.show_sql para que pueda ver en la consola todo el SQL que se está generando.

En el momento en que ocurre la congelación, puede averiguar qué filas están bloqueadas en la base de datos. por ejemplo, en SQLServer puede ejecutar sp_lock para ver esto y sp_who para ver qué ID de proceso SQL están bloqueando en otro.

Respondido el 08 de enero de 11 a las 22:01

Sí, también sospecho transacciones. Las pruebas se ejecutan linealmente (no sabía que PODRÍAN ejecutarse al mismo tiempo). hibernate.show_sql está activado, lo último que muestra es ELIMINAR DE SomeTable (de la configuración de prueba, que se completó correctamente). No muestra el inicio de la próxima consulta de Hibernate, el INSERT INTO ... Y por lo que puedo ver, no hay transacciones abiertas en MySQL. - cenizas999

Algunas cosas para comprobar:

  • Gestión adecuada de transacciones: parece que en su configuración tiene transacciones sobre un DAO suyo. Por lo general, es recomendable tener transacciones alrededor de su capa de servicio y no en el DAO. Pero de todos modos, asegúrese de tener una transacción alrededor del dao en uso por la prueba. O haz la prueba @Transactional (si usa el corredor junit de Spring)

  • cambiar el umbral de tala a info para la fuente de datos (c3p0, tal vez?). Informa de interbloqueos.

  • observe los registros de la base de datos para ver si hay puntos muertos (si existe esa opción)

Respondido el 09 de enero de 11 a las 01:01

Todo lo anterior está marcado, pero nada resuelve mi problema. Y la base de datos no mostró ningún punto muerto, lo cual es sospechoso. - cenizas999

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.