Dans Java/Hibernate application J'ai deux classes Cat
et Kitten
dans une relation bidirectionnelle comme dépeignent ci-dessous:Bi-direction devient beaucoup plus lent que uni direction
public class Cat {
...
@OneToMany(mappedBy="cat", fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
@LazyCollection(LazyCollectionOption.EXTRA)
@Getter
@Setter
private List<Kitten> kittens = new LinkedList();
public void addKitten(Kitten k) {
kittens.add(k);
}
...
}
public class Kitten {
...
@ManyToOne(fetch=FetchType.LAZY)
@Getter
@Setter
private Cat cat;
...
}
Dans une grande boucle for 20000 Kitten
sont ajouté à différentes entités Cat
qui ont été créées précédemment. Le code important dans la boucle for ressemble à ceci:
....
Kitten k = new Kitten();
k.setAttribut("foo");
k.setCat(currentCat); // (a) line
currentCat.addKitten(k); // (b) line
daoFactory.getKittenDao().save(k);
...
Le code fonctionne, mais en quelque sorte la performance est très lent. Dans une itération précédente (unidirectionnelle), l'application était beaucoup plus rapide. Depuis la version finale devrait fonctionner sur 1000000 Kitten
il doit y avoir un moyen d'améliorer. Si je compare l'heure du code ci-dessus, cela prend environ 40 secondes. Si je simule l'uni-direction en supprimant la ligne (a) ou (b), cela prend 10 secondes dans les deux cas (mais plus tard si j'accède aux objets). Donc, ma question est: Est-ce que quelque chose me manque ou est-ce que la maintenance interne des relations bidirectionnelles est très lente dans Hibernate? Puisque l'uni-direction simule est beaucoup plus rapide, je m'attendrais à une exécution d'environ 15 secondes pour la bidirection.
Mise à jour:
Le code de sauvegarde des entités est à l'intérieur d'une mise en œuvre SAX-Parser DefaultHandler. Ainsi, lors de l'analyse syntaxique de la structure XML, un Cat
est d'abord enregistré dans la fonction startElement()
et plus tard le Kitten
sera enregistré dans un autre appel startElement()
. En ce qui concerne les suggestions/questions par @Bartun: J'ai jeté un coup d'oeil dans le dosage. Le problème est, en utilisant DAO et les fonctions startElement()
, il est difficile de dire, quand exactement 50 entités ont été enregistrées pour vider la session. Un compteur pourrait faire l'affaire cependant. Cependant, cela n'explique pas l'impact sur les performances en établissant la bidirection. En tant que gestion des transactions, le ressort @Transactional
est utilisé sur la fonction qui démarre l'analyse XML.
Avez-vous profilé pour voir où vous saignez? – efekctive
Juste une supposition, essayez persist() plutôt que save(). – Steve11235
@ Steve11235 persistent le rend encore pire. Ensuite, le temps d'exécution est de 50 secondes. – Thanthla