Insert massif avec JPA + Hibernate
J'ai besoin de faire un énorme insertion à l'aide d'EJB 3, Hibernate, Spring Données et Oracle. A l'origine, je suis à l'aide de Données du Printemps et le code est ci-dessous:
talaoAITDAO.save(taloes);
Où talaoAITDAO une source de Données JpaRepository sous-classe et taloes est une Collection de TalaoAIT entité. Dans cette entité, Son ID a cette forme:
@Id
@Column(name = "ID_TALAO_AIT")
@SequenceGenerator(name = "SQ_TALAO_AIT", sequenceName = "SQ_TALAO_AIT", allocationSize = 1000)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQ_TALAO_AIT")
private Long id;
Aussi cette entité n'a pas d'entités liées, à faire de la cascade de l'insertion.
Mon problème ici, est que toutes les entités sont individuellement inséré (comme INSERT INTO TABLE(col1, col2) VALUES (val1, val2)
). Parfois, il peut entraîner un délai d'attente et toutes les insertions seront annulées. Je voudrais convertir ces insère dans le lot des inserts (comme INSERT INTO TABLE(col1, col2) VALUES (val11, val12), (val21, val22), (val31, val32), ...
).
D'étudier des solutions alternatives pour améliorer les performances, j'ai trouvé cette page en veille prolongée de la documentation, au-delà de
Hibernate taille de lot de confusion et cette autre page. Basé sur eux, j'ai écrit ce code:
Session session = super.getEntityManager().unwrap(Session.class);
int batchSize = 1000;
for (int i = 0; i < taloes.size(); i++) {
TalaoAIT talaoAIT = taloes.get(i);
session.save(talaoAIT);
if(i % batchSize == 0) {
session.flush();
session.clear();
}
taloes.add(talaoAIT);
}
session.flush();
session.clear();
Aussi, dans peristence.xml, j'ai ajouté ces propriétés:
<property name="hibernate.jdbc.batch_size" value="1000" />
<property name="order_inserts" value="true" />
Cependant, bien que dans mes tests, j'avais perçu une différence subtile (principalement avec de grandes collections et les grandes tailles de lots), il n'était pas si grand que souhaitable. Dans la journalisation de la console, j'ai vu que Hibernate suite à des différents inserts, pas de remplaçant pour le massif de l'insertion. Comme dans mon entité, je suis à l'aide d'un générateur de Séquence, je crois que c'est pas le problème (selon la documentation Hibernate, j'aurais eu de problème si j'ai été en utilisant l'Identité d'un générateur).
Donc, ma question est ce qui manque ici. Certains de configuration? Une méthode pas utilisé?
Merci,
Rafael Afonso.
source d'informationauteur Rafael Afonso | 2013-11-29
Vous devez vous connecter pour publier un commentaire.
Un couple de choses.
D'abord votre configuration propriétés sont mauvais
order_inserts
doit êtrehibernate.order_inserts
. Actuellement votre paramètre est ignoré et que vous n'avez pas changé d'une chose.La prochaine utilisation du
EntityManager
au lieu de faire tout ce qui est méchant hibernate choses. LeEntityManager
a aussi unflush
etclear
méthode. Cela devrait au moins le nettoyage de votre méthode. Sans l'ordre de cette aide un peu pour le nettoyage de la session et de prévention de la sale-les contrôles sur tous les objets.Ensuite, vous ne devriez pas prendre votre lots à grande car cela peut provoquer des problèmes de mémoire, commencer avec quelque chose comme 50 et test de qui/ce qui donne de meilleurs résultats. Il est un point sur lequel sale de vérification va prendre plus de temps, flusing et de compensation à la base de données. Vous souhaitez trouver cette sweet spot.
La solution posté par M. Deinum beaucoup travaillé pour moi, à condition que je les suivants Hibernate propriétés dans mon JPA
persistence.xml
fichier:Je suis en utilisant une base de données Oracle, alors j'ai aussi celle-ci définie: