2017-06-15 1 views
2

J'ai réussi à configurer Hibernate pour utiliser la requête par lots pour créer/mettre à jour des objets mais il y a un scénario qui ne fonctionne pas encore.Transaction par lot Hibernate avec plusieurs relations ManyToMany

J'ai 3 entités: - Entité principale - Entité A - Entité B

Entité principale a une relation ManyToMany avec les deux entités A et B. Entité Entité principale est le propriétaire de la relation:

@ManyToMany 
@JoinTable(name = "MAIN_A", joinColumns = { 
@JoinColumn(name = "MAIN_UID", nullable = false, updatable = false) }, inverseJoinColumns = { 
@JoinColumn(name = "A_UID", nullable = false, updatable = false) }) 
private Set<EntityA> entitiesA = new HashSet<>(0); 

@ManyToMany 
@JoinTable(name = "MAIN_B", joinColumns = { 
@JoinColumn(name = "MAIN_UID", nullable = false, updatable = false) }, inverseJoinColumns = { 
@JoinColumn(name = "B_UID", nullable = false, updatable = false) }) 
private Set<EntityB> entitiesB = new HashSet<>(0); 

J'ai écrit un test simple de 3. D'abord, je crée des lignes Entité A et Entité B dans la base de données (ceci est commun avec les 2 cas de test).

Premier scénario: Créer n Entité principale et pour chaque ensemble que l'entité A

Résultat: Un seul insert pour toutes les entrées de la table principale entité et MAIN_A. Donc, dans ce cas, l'insertion du bain fonctionne comme prévu.

Deuxième scénario: Créer n Entité principale et pour chaque ensemble que l'entité B

Résultat: Un seul insert pour toutes les entrées de la table Entité principale et MAIN_B. Donc, dans ce cas, l'insertion du bain fonctionne comme prévu.

Troisième scénario: Créer n Entité principale et pour chaque ensemble à la fois l'entité A et l'entité B

Résultat: Un seul insert pour toute la Entité principale et insérer n pour les deux MAIN A et MAIN_B entrées de table. Dans ce cas, l'insertion du lot n'a pas fonctionné. J'ai fait des recherches sur google, mais je n'ai pas trouvé de réponse.

Est-ce que quelqu'un sait pourquoi cela ne fonctionne pas comme prévu dans le troisième cas? Est-ce que je fais quelque chose de mal? Y a-t-il quelque chose dans la configuration qui répond à mes besoins?

Le code des 3 scénarios est assez simple:

Set<EntityA> setA; 
    Set<EntityB> setB; 
    for (long i = 1; i < n; i++) { 

    MainEntity e = new MainEntity(); 
    ac.setEntitiesA(setA); //this is commented in the second scenario 
    ac.setEntitiesB(setB); // this is commented in the first scenario 

    session.save(e); 
} 

J'ai posté le même qestion dans le forum de mise en veille prolongée: Hibernate Forum post

+0

pouvez-vous ajouter le code utilisé pour effectuer le 3ème scénario? –

+0

@MaciejKowalski Je viens de mettre à jour la question avec le code – Simone

Répondre

0

Il semble que vous enregistrez seulement le MainEntity (et je suppose l'entité A, B ajoutée aux ensembles sont de nouvelles entités).

À mon avis, vous devez ajouter au moins cette option en cascade à chacun de vos relations unidirectionnels:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) 

Sinon, vous devriez appeler économiser sur chacun des EntityA, EntityB.

+0

EntityA et EntityB sont enregistrés avant ... Ce que j'observe, c'est que les mises à jour dans les tableaux de relations n'utilisent pas l'insertion par lots dans le troisième scénario – Simone

+0

J'ai essayé quand même de changer le type de cascade mais il n'a fait aucune différence ... Mon problème n'est pas dans la création de EntityA et EntityB dans la base de données. Mon problème est de savoir comment Hibernate insère des données dans les tables de relation Main_A et Main_B ... dans le troisième scénario, l'insertion par lots n'est pas utilisée et Hibernate effectue 300 requêtes d'insertion au lieu de 1. Cela ne se produit pas dans les scénarios 1 et 2 et je n'ai pas encore trouvé d'explication! – Simone