Spring Data JPA Projection des champs sélectionnés dans la DB
J'ai été le tester Printemps de Données 1.10.4.La LIBÉRATION, à la suite de l'exemple au Printemps de Données Docs http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
et j'ai remarqué quelques problèmes pour lesquels j'ai 2 questions.
Première supposons que j'ai ces 2 entités:
@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;
}
- Question 1:
pour la suite des projections:
interface PersonLimited {
String getFirstName();
AddressLimited getAddress();
}
interface AddressLimited {
String getCountry();
}
quand je lance findPersonByFirstNameProjectedForlimiteddata
interface PersonRepository extends CrudRepository<Person, Long> {
@Query("select p from Person p where p.firstName = ?1")
PersonLimited findPersonByFirstNameProjectedForLimitedData(String firstName);
}
il retourne exactement ce qu'attend :
{
firstName: 'Homer',
address: {
country: 'USA'
}
}
maintenant, si je regarde dans le SQL généré, c'est ce que j'ai:
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 = ?
La projection de la "Personne" de l'entité est de sélectionner uniquement "fistName", ce qui est correct à 100% parce que dans le PersonLimited interface, je ne l'ai défini "getFirstName".
Mais pour l ' "Adresse" de l'entité, il sélectionne tous les champs, ce qui est faux parce que dans le AddressLimited interface, je ne l'ai défini "getCountry", Il convient de sélectionner uniquement "pays".
La requête générée doit être quelque chose comme:
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 = ?
donc la question est, pourquoi il n'est pas en sélectionnant uniquement le champ "pays" à l'Adresse "entité"? pourquoi il a besoin pour sélectionner tous les champs? est-ce un bug au Printemps?
- Question 2:
pour la même projection que ci-dessus,
quand je lance findAllPersonsProjectedForLimiteddata
interface PersonRepository extends CrudRepository<Person, Long> {
@Query("select p from Person p")
List<PersonLimited> findAllPersonsProjectedForLimitedData();
}
il retourne exactement ce qu'attend :
[
{
firstName: 'Homer',
address: {
country: 'USA'
}
},
{
firstName: 'Maggie',
address: {
country: 'USA'
}
}
]
maintenant, si je regarde dans le SQL généré, c'est ce que j'ai:
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 = ?
ici, la projection pour la Personne et l'Adresse des entités à sélectionner tous les champs qui est faux, il convient de sélectionner uniquement "prénom" et "pays".
La requête générée doit être quelque chose comme:
SELECT person0_.firstName AS firstName2_18_
FROM person person0_
SELECT address0_.country AS country4_13_0_
FROM address address0_
WHERE address0_.id = ?
est-ce le comportement normal de ne pas sélectionner uniquement les champs dont nous avons besoin?
Merci,
J'ai édité mes questions. le truc, c'est lors de l'utilisation de "Fermé Projection", comme celui que j'utilise, JPA doit uniquement sélectionner les champs que j'ai défini dans ma Projection des "interfaces". c'est ce que le Printemps de Données Doc a dit: Fermé projections exposer un sous-ensemble de propriétés par conséquent, ils peuvent être utilisés pour optimiser la requête de manière à réduire les champs sélectionnés dans la banque de données
ok, maintenant je comprends votre question. Très intéressante.
Je voudrais aller avec la manière standard od de projections sens "SÉLECTIONNEZ nouveau com.de l'entreprise.YourDto(p.prénom, p.adresse.pays) DE la Personne p". Il vous offre plus de possibilités dans votre DTO que dans cette approche de l'interface.
2 ans après et personne ne répond 🙁
OriginalL'auteur arammal | 2016-10-22
Vous devez vous connecter pour publier un commentaire.
Si vous voulez utiliser l'annotation @Requête Ressort avec des Projections de Données, vous devez utiliser des alias de champ et vous devez vous assurer que vous alias les projets correspondant à la projection des champs. Le code suivant devrait fonctionner pour la question 1:
Une autre solution de rechange que vous pouvez utiliser est de définir vos requêtes avec Les Expressions De Propriété. chaque fois que c'est possible:
"select new org.example.PersonLimited(p.firstName, p.address) from Person p where p.firstName = ?1"
.OriginalL'auteur Andrés Cuadros Suárez