bonjour,
je travaille actuellement sur les performances de l'application de mon travail et je suis confronté au problèmes du N+1 requetes lors du save.
j'utilise Hibernate
<hibernate.version>3.6.10.Final</hibernate.version>
et java 1.6
Je dispose d'un objet java qui est LigneCommande
Code:
@Entity
@Table(name = "lignecommande")
public class LigneCommande {
..
private Produit produit;
@OneToOne
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_produit")
public Produit getProduit() {
return produit;
}
}
je n'ai pas mis tout les paramètres mais uniquement celui qui me pose problème, à savoir produit.
lors du passage d'une commande, j'ai besoin d'enregistrer les lignes de commande associé, et lors de ce processus je fait cela :
Code:
for (CmdDetailDTO cmdDetailDTO : cmdDetailDTOs) {
LigneCommande ligneCommande = new LigneCommande();
Produit produit = produitDao.load(cmdDetailDTO.getProduitId());
ligneCommande.setProduit(produit);
ligneCommandeDao.save(ligneCommande);
}
étant donné que je n'ai pas besoin de mon produit lors de l'enregistrement de la ligne car je n'ai aucune getter à appeler, j'utilise la méthode Load afin d'en avoir un proxy et donc éviter de requeter la base de données, ce qui aura pour objet de me renseigner ma fk_produit dans lignecommande.
malgré cela lors du commit de la transaction, je vois passer le select sur le produit
voila ce que j'ai dans les logs lors de l'ajout d'une seule ligne:
Code:
Hibernate:
select
nextval ('public.LigneCommandeId_seq')
Hibernate:
select
produit0_.id as id521_5_,
...
...
where
produit0_.id=?
Hibernate:
insert
into
public.lignecommande
(groupeid, ajoutManuel, fk_commande, datemodification, estAcceptee, ligneModifiee, motif, moyenneVente, ordreCatalogue, ordreDansCommande, ordreDuTri, prixUnitaire, fk_produit, quantiteCommandee, quantiteEnCours, quantiteEnvoyee, fk_referenceproduitfournisseur, stockCurrent, stockUniteCurrent, id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
donc autant dire que si j'ajoute 100 lignes dans ma commande j'aurai 100 requetes select et niveau perf ce n'est pas top.
pour le moment pour éviter d'avoir les select j'ai créé une méthode dans mon dao qui charge les données dans le cache hibernate
Code:
builder.append("select p from Produit as p join fetch p.categorieFamille fam join fetch p.TVA where p.id in (:produitIds) ");
Query query = getSession().createQuery(builder.toString());
query.setParameterList("produitIds", produitIds);
query.list();
ce qui a pour effet de ne générer qu'une seule requete que j'ajoute 1 ou 100 produits.
mais bon cela ne me plait pas car je pensais que la méthode Load faisait dejà son travail afin d'empecher le select, étant donné que je ne fait jamais d'appel à une méthode get sur mon entité produit.
après si quelqu un peut me dire dans le code hibernate ou se trouve l'endroit qui check si une entité doit etre récupéré ou non de la base, cela m'interesse, je pourrais essayer de voir la condition qui fait que mon entité est récupéré.
merci d'avance!