0
votes

Comment utiliser un autre nom de variable ou Comment aplatir une entité dans JPA Projection pour un objet imbriqué

Je crée une API pour interroger une entité imbriquée avec Spring Data JPA Projection.

Mon code

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"
    }
}

Réponse attendue

{
    "name": "example",
    "city": "example-city",
    "country": "example-country"
}

Mon code produit

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é

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?


5 commentaires

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.


3 Réponses :


0
votes

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


0 commentaires

0
votes

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>
}


0 commentaires

0
votes

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.


0 commentaires