En toute sécurité de compensation de la session Hibernate dans le milieu de la grande opération

Je suis à l'aide de Spring+Hibernate pour une opération qui nécessite la création et la mise à jour des centaines de milliers d'articles. Quelque chose comme ceci:

{
   ...
   Foo foo = fooDAO.get(...);
   for (int i=0; i<500000; i++) {
      Bar bar = barDAO.load(i);
      if (bar.needsModification() && foo.foo()) {
         bar.setWhatever("new whatever");
         barDAO.update(bar);
         //commit here
         Baz baz = new Baz();
         bazDAO.create(baz);
         //if (i % 100 == 0), clear
      }
   }
}

Pour me protéger contre les perdre les modifications dans le milieu, j'valider les modifications immédiatement après barDAO.update(bar):

HibernateTransactionManager transactionManager = ...; //injected by Spring
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus transactionStatus = transactionManager.getTransaction(def);
transactionManager.commit(transactionStatus);

À ce point, je dois dire que tout le processus est en cours d'exécution dans une transaction enveloppé dans org.springframework.orm.hibernate3.support.ExtendedOpenSessionInViewFilter (oui, c'est une webapp).

Tout cela fonctionne très bien avec une seule exception: après quelques milliers de mises à jour/s'engage, tout le processus est très lent, très probablement due à mémoire de ballonnement l'augmentation constante du nombre d'objets conservés par Spring/Hibernate.

En veille prolongée environnement uniquement ce serait facilement résoluble en appelant org.hibernate.Session#clear().

Maintenant, les questions:

  • Quand est-il un bon moment pour clear()? A-t-elle une grande performance coût?
  • Pourquoi ne sont pas des objets comme des bar ou baz libéré/Pgcd automatiquement? Quel est le point de les maintenir dans la session après la validation (dans la boucle d'itération ils ne sont pas accessible de toute façon)? Je n'ai pas fait de vidage de mémoire pour prouver cela, mais mon sentiment est qu'ils sont encore là jusqu'à ce que complètement quitté. Si la réponse est "Hibernate cache", alors pourquoi n'est-ce pas le cache est vidé sur la mémoire disponible va faible?
  • est-il sécuritaire/recommandé d'appeler org.hibernate.Session#clear() directement (en ayant à l'esprit tout le Printemps contexte, des choses comme le chargement paresseux, etc.)? Sont-il utilisable Printemps wrappers/contreparties pour atteindre le même?
  • Si la réponse à la question ci-dessus est vrai, ce qui va se passer avec l'objet foo, en supposant clear() est appelée à l'intérieur de la boucle? Que faire si foo.foo() est un paresseux-la méthode de chargement?

Merci pour les réponses.

  • Je suis également de la réalisation de plusieurs grands inserts. L'ajout de code pour rincer et effacer la séance occasionnellement viens de faire mon code exécuté à 4x plus rapide!
InformationsquelleAutor mindas | 2010-09-24