2016-01-04 7 views
6

Ich habe folgende 2 Einheiten:Unterschied zwischen verbinden und Pfadnavigation in JPA Query

class User { 
private String name; 
private UserType userType; 
} 

class UserType { 
private String name; 
} 

ich alle Benutzer mit Namen usertype gleich ‚admin‘ holen will. Ich kann die folgenden 2 Abfragen schreiben, die das gleiche Ergebnis zurückgeben.

select u from User u where u.userType.name = 'admin'; 

und

select u from User u join u.userType ut where ut.name = 'admin'; 

Ich wollte nur verstehen, welcher Ansatz vorzuziehen ist, und was ist der Unterschied. Wenn ich immer das Ergebnis über die Navigation zwischen Entitäten erhalten kann, wann soll ich dem Join-Ansatz folgen?

+2

Was ist, wenn Sie eine linke äußere Verbindung benötigen? Darüber hinaus ist der erste Ansatz, der einen impliziten Join erzeugt, vermeidbar, da er je nach dem verwendeten JPA-Provider einen Cross-Join erzeugen kann. Daher sollten Sie immer darauf achten, die generierten SQL-Anweisungen genau zu beobachten. – Tiny

Antwort

2

Bei der Analyse des von den beiden Abfragen generierten SQL (jpa + Spring Data) wurde beobachtet, dass die Navigation zu einem Cross-Join führt, während die Erwähnung von nur 'Join' standardmäßig zu einem inneren Join führt.

Daher Navigation ist nicht so effizient wie explizit Beitritt zu den erforderlichen Spalten.

+1

Es scheint keine allgemeine Übereinstimmung über dieses Verhalten zu geben. Hibernate erzeugt unerwartet einen Cross-Join, EclipseLink erzeugt wie erwartet einen inneren Join, andere Provider können ihr eigenes Verhalten haben. Man sollte offensichtlich nicht von diesem irritierenden Verhalten verschiedener Anbieter abhängig sein, was dann zu einer nicht-portablen Geschäftslogik über verschiedene Anbieter hinaus führen wird, in der keines der proprietären Merkmale überhaupt verwendet wird. – Tiny

2

Technisch sind sie gleichwertig, aber die zweite ist viel flexibler.

Mit der expliziten Join-Syntax können Sie die JOIN-LEFT JOIN mit einem ON Kriterien ändern:

select u 
from User u 
left join u.userType ut on ut.name = 'admin' 

Diese Abfrage wird immer ein Benutzer zurück, auch wenn es nicht einen Benutzertyp hat, so manchmal ist das wünschenswert für einige besondere Anwendungsfälle.

Verwandte Themen