Spring Data JPA Projection ausgewählte Felder aus der DB
Ich habe Spring Data 1.10.4.RELEASE getestet, entsprechend dem Beispiel in Spring Data Docshttp: //docs.spring.io/spring-data/jpa/docs/current/reference/html/#projection
und mir sind einige Probleme aufgefallen, für die ich 2 Fragen habe.
Zunächst nehme ich an, ich habe diese 2 Entitäten:
@Entity
public class Person {
@Id @GeneratedValue
private Long id;
private String firstName, lastName;
@OneToOne
private Address address;
}
@Entity
public class Address {
@Id @GeneratedValue
private Long id;
private String street, state, country;
}
Frage 1für die folgenden Projektionen:
interface PersonLimited {
String getFirstName();
AddressLimited getAddress();
}
interface AddressLimited {
String getCountry();
}
wenn ich renne findPersonByFirstNameProjectedForLimitedData
interface PersonRepository extends CrudRepository<Person, Long> {
@Query("select p from Person p where p.firstName = ?1")
PersonLimited findPersonByFirstNameProjectedForLimitedData(String firstName);
}
it gibt genau das zurück, was erwartet wurde:
{
firstName: 'Homer',
address: {
country: 'USA'
}
}
Nun, wenn ich in die generierte SQL schaue, ist dies das, was ich habe:
SELECT person0_.firstName AS col_0_0_,
address1_.id AS id1_13_,
address1_.street AS street2_13_,
address1_.state AS state3_13_,
address1_.country AS country4_13_
FROM person person0_
LEFT OUTER JOIN address address1_
ON person0_.addressId = address1_.id
WHERE person0_.firstName = ?
Die Projektion für die Entität "Person" wählt nur "fistName" aus, was zu 100% korrekt ist, da ich in der PersonLimited-Schnittstelle nur "getFirstName" definiert habe.
Aber für die Entität "Address" werden alle Felder ausgewählt, was falsch ist, da in der AddressLimited-Schnittstelle, die ich nur als "getCountry" definiert habe, nur "country" ausgewählt werden sollte.
Die generierte Abfrage sollte ungefähr so aussehen:
SELECT person0_.firstName AS col_0_0_,
address1_.country AS country4_13_
FROM person person0_
LEFT OUTER JOIN address address1_
ON person0_.addressId = address1_.id
WHERE person0_.firstName = ?
so die Frage ist, warum es nicht nur das Feld "Land" für die Adresse "Entität" auswählt? Warum muss es alle Felder auswählen? ist es ein Fehler im Frühjahr?
Frage 2für die gleiche Projektion wie oben,
wenn ich renne findAllPersonsProjectedForLimitedData
interface PersonRepository extends CrudRepository<Person, Long> {
@Query("select p from Person p")
List<PersonLimited> findAllPersonsProjectedForLimitedData();
}
it gibt genau das zurück, was erwartet wurde:
[
{
firstName: 'Homer',
address: {
country: 'USA'
}
},
{
firstName: 'Maggie',
address: {
country: 'USA'
}
}
]
Nun, wenn ich in die generierte SQL schaue, ist dies das, was ich habe:
SELECT person0_.id AS id1_18_,
person0_.firstName AS firstName2_18_,
person0_.lastName AS lastName3_18_,
person0_.addressid AS company4_18_
FROM person person0_
SELECT address0_.id AS id1_13_0_,
address0_.street AS street2_13_0_,
address0_.state AS state3_13_0_,
address0_.country AS country4_13_0_
FROM address address0_
WHERE address0_.id = ?
Hier werden in der Projektion für die Entitäten "Person" und "Adresse" alle falschen Felder ausgewählt. Es sollten nur "Vorname" und "Land" ausgewählt werden.
Die generierte Abfrage sollte ungefähr so aussehen:
SELECT person0_.firstName AS firstName2_18_
FROM person person0_
SELECT address0_.country AS country4_13_0_
FROM address address0_
WHERE address0_.id = ?
Ist dies das normale Verhalten, sollten nicht nur die Felder ausgewählt werden, die wir benötigen?
Vielen Dank