Une approche naïve pour insérer 100 000 lignes dans la base de données en utilisant Hibernate pourrait ressembler à ça :
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); session.save(customer); } tx.commit(); session.close();
Ceci devrait s'écrouler avec une OutOfMemoryException
quelque part aux alentours de la 50 000ème ligne. C'est parce qu'Hibernate cache toutes les instances de Customer
nouvellement insérées dans le cache de second niveau.
Dans ce chapitre nous montrerons comment éviter ce problème. D'abord, cependant, si vous faites des traitements par batch, il est absolument critique que vous activiez l'utilisation ds paquet JDBC (NdT : JDBC batching), si vous avez l'intention d'obtenir des performances raisonnables. Configurez la taille du paquet JDBC avec un nombre raisonnable (disons, 10-50) :
hibernate.jdbc.batch_size 20
Vous pourriez aussi vouloir faire cette sorte de travail dans un traitement où l'interaction avec le cache de second niveau est complètement désactivé :
Insertions en paquet
hibernate.cache.use_second_level_cache false
Lorsque vous rendez des nouveaux objets persistants, vous devez régulièrement appeler flush()
et puis clear()
sur la session, pour contrôler la taille du cache de premier niveau.
Pour récupérer et mettre à jour des données les mêmes idées s'appliquent. En plus, vous avez besoin d'utiliser scroll()
pour tirer partie des curseurs côté serveur pour les requêtes qui retournent beaucoup de lignes de données.
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); session.save(customer); if ( i % 20 == 0 ) { //20, same as the JDBC batch size //flush a batch of inserts and release memory: session.flush(); session.clear(); } } tx.commit(); session.close();