Je crée une API pour interroger une entité imbriquée avec Spring Data JPA Projection.
L'entité:
interface UserView { val name: String val addressCity: String val addressCountry: String }
Le référentiel:
{ "name": "example", "address": { "city": "example-city", "country": "example-country" } }
{ "name": "example", "city": "example-city", "country": "example-country" }
interface UserView { val name: String val address: AddressView interface AddressView { val city: String val country: String } } @Repository interface UserRepository : JPARepository<User, String> { fun findAll(): List<UserView> }
J'ai essayé une autre vue pour aplatir l'objet:
@Entity class User { @Id var userId: String var name: String var age: Int @OneToOne @JoinColumn(name = "userId") var address: Address } @Entity class Address { var userId: String var street: String var city: String var country: String }
Mais dans ce cas, la dénomination des variables est trop compliquée.
Je veux résoudre ce problème avec la projection. Comment puis-je résoudre ce problème?
3 Réponses :
Dans JPA, vous pouvez le faire en utilisant uniquement @NamedNativeQuery
:
@NamedNativeQuery( name = "getUser", query = "SELECT u.name, a.city, a.country FROM User u and Address a where a.userId = u.id ", resultClass=UserView .class) @Entity class User { ... }
Pour référence hibernate-named-query
Essaye ça:
data class UserView(name: String, city: String, country: String) @Repository interface UserRepository : JPARepository<User, String> { @Query(value = "select new your.pkg.UserView(u.name, u.address.city, u.address.country) from User u") fun findAllFlat(): List<UserView> }
Vous pouvez utiliser @Value
et combiner plus de champs ou même accéder aux champs d'objets.
À partir de la documentation spring-data-rest :
@Value("#{target.document.title}") String getDocumentTitle();
L'aplatissement fonctionne aussi pour moi:
You can create a projection that combines the two data fields in the preceding example together, as follows: @Projection(name = "virtual", types = { Person.class }) public interface VirtualProjection { @Value("#{target.firstName} #{target.lastName}") String getFullName(); } Springâs @Value annotation lets you plug in a SpEL expression that takes the target object and splices together its firstName and lastName attributes to render a read-only fullName.
Je n'ai pas d'expérience en kotlin, mais pour le faire en JPA: (i) vous pouvez essayer de
join
également comme àfrom User u join u.address
ce qui donne une table.Je ne veux pas utiliser de requête native pour résoudre ce problème. Existe-t-il un autre moyen d'utiliser l'API JPA?
Je ne pense pas qu'il existe un moyen de faire cela dans JPA autre que @NamedNativeQuery
Je veux résoudre ce problème avec la projection . Vous pouvez résoudre ce était une projection. Quel est le problème que vous rencontrez en utilisant cette approche?
Je veux aplatir cet objet de réponse comme ci-dessus JSON. Mais la projection ne peut pas aplatir cet objet de réponse comme ci-dessous JSON.