2011-01-08 3 views
3

J'utilise Hibernate et Spring avec le pattern DAO (toutes les dépendances d'Hibernate dans une classe * DAO.java). J'ai neuf tests unitaires (JUnit) qui créent des objets métier, les sauvegardent et effectuent des opérations sur eux; les objets sont dans un hachage (donc je réutilise les mêmes objets tout le temps).Hibernate/Spring: getHibernateTemplate(). Save (...) Gèle/se bloque

Ma méthode d'installation JUnit appelle ma méthode DAO.deleteAllObjects() qui appelle getSession().createSQLQuery("DELETE FROM <tablename>").executeUpdate() pour ma table d'objets métier (une seule).

Un de mes tests unitaires (# 8/9) se bloque. J'ai supposé qu'il s'agissait d'un blocage de base de données, car le fichier journal Hibernate affiche mon instruction delete en dernier. Cependant, le débogage a montré que c'est simplement HibernateTemplate.save(someObject) qui gèle. (Eclipse montre qu'il gèle sur HibernateTemplate.save(Object), ligne 694.)

Il est également intéressant de noter que l'exécution de ce test en lui-même (pas dans la suite de 9 essais) ne pose aucun problème.

Comment diable puis-je résoudre ce problème?

En outre, j'utilise @Entity annotations, si cela est important.

Modifier: J'ai supprimé la réutilisation de mes objets métier (utilisez des objets uniques dans chaque méthode) - n'a pas fait de différence (reste figé).

Edit: Cela a commencé ruisseler dans d'autres tests aussi (ne peut pas exécuter plus d'une classe de test sans obtenir le gel de quelque chose)

Edit: Briser les essais de gel en deux classes fonctionne. Je vais le faire pour l'instant, aussi honteusement pas DRY que c'est le cas pour avoir deux ou plusieurs classes de test testant l'unité de la même classe d'objet métier.

configuration de la transaction:

<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> 
+0

commettez-vous des transactions après chaque méthode d'essai? – Bozho

+0

Je suis un hibernate n00b (plus expérimenté avec NHibernate - pratiquement aucune configuration requise), donc je vais faire l'hypothèse que oui, je le suis. J'ai modifié ma réponse pour inclure une configuration transactionnelle. J'ai également essayé d'appeler session.flush() et transaction.flush(), en vain. – ashes999

Répondre

1

Lorsque le gel se casser la demande, trouver le fil conducteur et capturer le stacktrace. Passer en revue jusqu'à ce que vous trouviez exactement quelle requête DB est en cours d'exécution qui bloque dans la base de données.

Vous parlez d'exécuter le test sur son propre fonctionne bien, mais l'exécution de la suite complète provoque un problème. Si tel est le cas, je suppose que l'un des tests précédents a toujours une transaction ouverte et verrouille sur certaines lignes auxquelles le test de blocage tente d'accéder.

Vos tests sont-ils exécutés simultanément? Si c'est le cas, arrêtez de le faire car ils pourraient interférer les uns avec les autres. Activez l'option hibernate.show_sql pour que vous puissiez voir dans la console tout le SQL en cours de génération.

Au point où le gel se produit, pouvez-vous trouver quelles lignes sont verrouillées dans le DB.? par exemple. Dans SQLServer, vous pouvez exécuter sp_lock pour voir ceci et sp_who pour voir quels identifiants de processus SQL bloquent sur un autre.

+0

Oui, je suspecte des transactions aussi bien. Les tests sont linéaires (ne savaient pas qu'ils pourraient être exécutés simultanément). 'hibernate.show_sql' est activé, la dernière chose qu'il affiche est DELETE FROM SomeTable (de la configuration du test, qui s'est terminée avec succès). Il ne montre pas le début de la prochaine requête Hibernate, l'INSERT INTO ... Et autant que je puisse voir, il n'y a pas de transactions ouvertes dans MySQL. – ashes999

1

Quelques choses à vérifier:

  • gestion des transactions correcte - il semble que dans votre configuration, vous avez des transactions sur un OTI de la vôtre. Généralement, il est conseillé d'avoir des transactions autour de votre couche de service, et non le DAO. Mais de toute façon - assurez-vous que vous avez une transaction autour du dao en cours d'utilisation par le test. Ou faites le test @Transactional (si vous utilisez le runner junit du ressort)

  • modifiez le protocole de journalisation à info pour la source de données (c3p0, peut-être?). Il signale des blocages.

  • regarder les journaux de base de données pour les interblocages (si cette option)

+0

Tout ce qui précède est vérifié, mais rien de tout cela résout mon problème. Et la base de données n'a montré aucun blocage, ce qui est suspect. – ashes999