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.addressce 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.