2011-03-08 5 views
1

Je viens de mettre en place un test qui vérifie que je suis capable d'insérer des entrées dans ma base de données en utilisant Hibernate. Ce qui me rend fou, c'est qu'Hibernate ne supprime pas les entrées, bien qu'il rapporte qu'elles sont parties!Hibernate ne supprime pas mes objets. Pourquoi?

Le test ci-dessous s'exécute avec succès, mais quand je vérifie ma base de données par la suite, les entrées qui ont été insérées sont toujours là! J'essaie même de le vérifier en utilisant assert (oui j'ai le paramètre -m comme vm). Quelqu'un at-il une idée pourquoi les entrées ne sont pas supprimées?

public class HibernateExportStatisticDaoIntegrationTest { 
    HibernateExportStatisticDao dao; 
    Transaction transaction; 

    @Before 
    public void setUp(){ 
     assert numberOfStatisticRowsInDB() == 0; 
     dao = new HibernateExportStatisticDao(HibernateUtil.getSessionFactory()); 
    } 

    @After 
    public void deleteAllEntries(){ 
     assert numberOfStatisticRowsInDB() != 0; 
     Session session = HibernateUtil.getSessionFactory().getCurrentSession(); 
     for(PersistableStatisticItem item:allStatisticItemsInDB()) { 
      session.delete(item); 
     } 
     session.flush(); 
     assert numberOfStatisticRowsInDB() == 0; 
    } 

    @Test public void exportAllSavesEntriesToDatabase(){ 
     int expectedNumberOfStatistics = 20; 
     dao.exportAll(StatisticItemFactory.createTestStatistics(expectedNumberOfStatistics)); 

     assertEquals(expectedNumberOfStatistics, numberOfStatisticRowsInDB()); 
    } 

    private int numberOfStatisticRowsInDB() { 
     return allStatisticItemsInDB().size(); 
    } 

    @SuppressWarnings("unchecked") 
    private List<PersistableStatisticItem> allStatisticItemsInDB(){ 
     Session session = HibernateUtil.getSessionFactory().getCurrentSession(); 
     transaction = session.beginTransaction(); 
     Query q = session.createQuery("FROM PersistableStatisticItem item"); 
     return q.list(); 
    } 
} 

La console est rempli de

Hibernate: delete from UPTIME_STATISTICS where logDate=? and serviceId=? 

mais rien n'a été supprimé quand je vérifierai.

Répondre

4

Je suppose que c'est lié à l'utilisation incohérente des transactions (notez que beginTransaction() dans allStatisticItemsInDB() est appelé plusieurs fois sans commits correspondants).

Essayez de gérer les transactions de manière appropriée, par exemple, comme ceci:

Session session = HibernateUtil.getSessionFactory().getCurrentSession(); 
Transaction tx = session.beginTransaction(); 
for(PersistableStatisticItem item: 
    session.createQuery("FROM PersistableStatisticItem item").list()) { 
    session.delete(item); 
} 
session.flush(); 
assert session.createQuery("FROM PersistableStatisticItem item").list().size() == 0; 
tx.commit(); 

Voir aussi:

+0

Vous avez probablement raison, sachant que ma connaissance de l'utilisation correcte d'Hibernate est proche de 'nil'. J'examinerai comment cela fonctionne quand je retournerai au travail demain et rendrai compte. Merci! – oligofren

+0

Vous aviez raison au sujet des transactions étant la cause, bien que votre code fourni n'était pas assez. Si vous utilisez votre code, j'obtiendrai une exception disant que la session a été fermée quand je suis arrivé à session.delete(). Je ne suis pas tout à fait sûr pourquoi, mais je suppose qu'il est plus logique d'ouvrir une nouvelle session pour chaque opération logique (éventuellement composée de plusieurs transactions). – oligofren

+0

N'a pas tout à fait fini là ... Pour que tout fonctionne, c'est essentiellement ce que j'ai fait. Dans chaque méthode qui impliquait des requêtes sur la base de données/Hibernate I: - ouvrait une nouvelle session. Session session = HibernateUtil.getSessionFactory(). OpenSession(); - a démarré une nouvelle transaction 'session.beginTransaction(); ' - a validé la transaction ' session.flush(); ' ' session.getTransaction(). commit(); ' – oligofren

0

Pouvez-vous publier votre schéma DB et Cartes HBM ou Fluent? Une chose qui m'a un peu de temps en arrière était que j'avais un ReadOnly() dans ma carte Fluent. Il n'a jamais jeté une erreur et j'ai aussi vu le "supprimer de blah où blahblah = ..." dans les journaux.

+0

Je vais essayer ça demain, après avoir vérifié si la transaction ci-dessus s'avère fructueuse. Merci! – oligofren

+0

Il semble que ce soit ma manière bâclée de commencer/terminer les transactions qui a créé des problèmes. Merci quand même. – oligofren

1

J'ai le même problème. Bien que je n'utilisais pas la transaction du tout. J'utilisais namedQuery comme ceci:

Query query = session.getNamedQuery(EmployeeNQ.DELETE_EMPLOYEES); 
int rows = query.executeUpdate(); 
session.close(); 

Il renvoyait 2 lignes mais la base de données contenait toujours tous les enregistrements. Puis je enveloppe le code ci-dessus avec ceci:

Transaction transaction = session.beginTransaction(); 
Query query = session.getNamedQuery(EmployeeNQ.DELETE_EMPLOYEES); 
int rows = query.executeUpdate(); 
transaction.commit(); 
session.close(); 

Ensuite, il a commencé à fonctionner correctement. J'utilisais le serveur SQL. Mais je pense que si nous utilisons h2, le code ci-dessus (sans transaction) fonctionnera également très bien. Encore une observation: Pour insérer et obtenir des enregistrements, l'utilisation de la transaction n'est pas obligatoire mais pour la suppression des enregistrements, nous devrons utiliser la transaction. (seulement testé dans le serveur SQL)

Questions connexes