FetchMode-Join macht keinen Unterschied für ManyToMany-Relationen in Spring-JPA-Repositories

8

Ich versuche das zu tun:

%Vor%

es erzeugt n + 1 Abfragen, wenn ich personRepository.findAll(); über ein Spring JPA-Repository mache, so als ob ich kein @Fetch gesetzt hätte. (Eine Abfrage zuerst, um alle Personen zu erhalten, und dann eine Abfrage pro Person, um die Gruppen zu holen).

Die Verwendung von @Fetch(FetchMode.SUBSELECT) funktioniert jedoch ! Es generiert nur 2 Abfragen. (Einer für alle Personen und dann einer für die Gruppen). Der Hibernate reagiert also auf einige Abrufparameter, nur nicht auf den JOIN .

Ich habe auch versucht, das EAGER fetching ohne Glück zu entfernen.

%Vor%

Ich verwende Spring JPA, und dies ist der Code für mein Repository:

%Vor%

Arbeitet JOIN einfach nicht mit Spring JPA oder mache ich etwas falsch?

    
Matsemann 19.09.2013, 10:05
quelle

2 Antworten

20

Gehen Sie durch viele Foren und Blogs, um nach Ihrem Problem zu lesen (ich nehme an, Sie haben das vielleicht getan, bevor Sie es hier gepostet haben). Ich denke auch, dass

  

@Fetch (FetchMode.JOIN) wird ignoriert, wenn Sie die Query-Schnittstelle verwenden   (z. B. session.createQuery ()), aber es wird ordnungsgemäß verwendet, wenn Sie verwenden   die Kriterienschnittstelle.

     

Dies ist praktisch ein Fehler in Hibernate, der nie gelöst wurde. Es ist   bedauerlich, da viele Anwendungen die Query-Schnittstelle verwenden und   kann nicht einfach auf die Kriterienschnittstelle migriert werden.

     

Wenn Sie die Query-Schnittstelle verwenden, müssen Sie immer JOIN FETCH hinzufügen   Anweisungen in den HQL manuell.

Referenzen Hibernate Forum Spring Forum Ähnliche Frage 1

    
DarkHorse 27.09.2013 10:42
quelle
9

Ich konnte auch @Fetch(FetchMode.JOIN) nicht verwenden, wenn ich JPA benutze (obwohl es gut funktioniert, wenn ich den Hibernate Criteria API benutze) und ich konnte auch keine Beispiele finden, die erklären warum, aber ich kann an einige Problemumgehungen denken.

Der einfachste Weg, um die Gruppen eifrig zu laden, ist die Verwendung von JPQL:

%Vor%

Da Sie spring-data-jpa verwenden, können Sie die Gruppen auch gerne mit einem Specification laden. (Ab 1.4.x können Sie Spezifikationen ketten, die null zurückgeben).

%Vor%

Wenn keine dieser Optionen für Sie geeignet ist, verwenden Sie am besten @Fetch(FetchMode.SUBSELECT) .

Eine andere Option ist die Verwendung von @Fetch(FetchMode.SELECT) in Kombination mit @BatchSize . @BatchSize hilft, das Problem der n + 1 Abfragen zu lösen. Durch Anpassen der Stapelgröße können Sie die Anzahl der Abfragen reduzieren, die an CEIL (n / batch_size) +1 ausgeführt werden.

%Vor%

Diese Zuordnung führt zu der folgenden SQL, wenn Sie personRepository.findAll(); in einer Datenbank mit 10 Personen und @BatchSize auf 5 setzen.

%Vor%

Beachten Sie, dass @BatchSize auch für Sammlungen funktioniert, die mit FetchType.LAZY zugeordnet sind.

    
Pieter 27.09.2013 23:03
quelle