web-dev-qa-db-fra.com

POST d’une association de sous-ressources @OneToMany dans Spring Data REST

Actuellement, j'ai une application Spring Boot qui utilise Spring Data REST. J'ai une entité de domaine Post qui a le @OneToMany relation avec une autre entité de domaine, Comment. Ces classes sont structurées comme suit:

Post.Java:

@Entity
public class Post {

    @Id
    @GeneratedValue
    private long id;
    private String author;
    private String content;
    private String title;

    @OneToMany
    private List<Comment> comments;

    // Standard getters and setters...
}

Commentaire.Java:

@Entity
public class Comment {

    @Id
    @GeneratedValue
    private long id;
    private String author;
    private String content;

    @ManyToOne
    private Post post;

    // Standard getters and setters...
}

Leurs référentiels Spring REST), les référentiels JPA sont des implémentations de base de CrudRepository:

PostRepository.Java:

public interface PostRepository extends CrudRepository<Post, Long> { }

CommentRepository.Java:

public interface CommentRepository extends CrudRepository<Comment, Long> { }

Le point d’entrée de l’application est une application standard et simple de démarrage Spring Boot. Tout est configuré stock.

Application.Java

@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {

    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Tout semble fonctionner correctement. Lorsque je lance l'application, tout semble fonctionner correctement. Je peux POST un nouvel objet Post à http://localhost:8080/posts ainsi:

Corps: {"author":"testAuthor", "title":"test", "content":"hello world"}

Résultat à http://localhost:8080/posts/1:

{
    "author": "testAuthor",
    "content": "hello world",
    "title": "test",
    "_links": {
        "self": {
            "href": "http://localhost:8080/posts/1"
        },
        "comments": {
            "href": "http://localhost:8080/posts/1/comments"
        }
    }
}

Cependant, lorsque j'effectue une opération GET à http://localhost:8080/posts/1/comments Je reçois un objet vide {} est retourné et si j'essaie de POST un commentaire sur le même URI, j'obtiens une méthode HTTP 405 non autorisée.

Quelle est la bonne façon de créer une ressource Comment et de l’associer à cette Post? J'aimerais éviter de poster directement à http://localhost:8080/comments si possible.

100
ccampo

Vous devez d'abord publier le commentaire et, tout en publiant le commentaire, vous pouvez créer une entité qui publie une association.

Cela devrait ressembler à quelque chose comme ci-dessous:

http://{server:port}/comment METHOD:POST

{"author":"abc","content":"PQROHSFHFSHOFSHOSF", "post":"http://{server:port}/post/1"}

et cela fonctionnera parfaitement bien.

48
Chetan Kokil

En supposant que vous ayez déjà découvert l’URI de publication et donc l’URI de la ressource d’association (considérée comme étant $association_uri dans la suite), il faut généralement:

  1. Découvrez les commentaires de gestion de la ressource de collection:

    curl -X GET http://localhost:8080
    
    200 OK
    { _links : {
        comments : { href : "…" },
        posts :  { href : "…" }
      }
    }
    
  2. Suivez le lien comments et POST vos données à la ressource:

    curl -X POST -H "Content-Type: application/json" $url 
    { … // your payload // … }
    
    201 Created
    Location: $comment_url
    
  3. Assignez le commentaire à la publication en envoyant un PUT à l'URI de l'association.

    curl -X PUT -H "Content-Type: text/uri-list" $association_url
    $comment_url
    
    204 No Content
    

Notez que dans la dernière étape, selon la spécification de text/uri-list , vous pouvez soumettre plusieurs URI identifiant des commentaires séparés par un saut de ligne pour attribuer plusieurs commentaires à la fois.

Quelques notes supplémentaires sur les décisions de conception générale. Un exemple post/comments est généralement un excellent exemple d'agrégat. Cela signifie que j'éviterais la référence arrière du Comment au Post et éviterais également le CommentRepository. complètement. Si les commentaires n'ont pas eux-mêmes de cycle de vie (ce qu'ils ne font généralement pas dans une relation composition-style), vous obtenez plutôt les commentaires restitués directement dans la ligne et vous pouvez traiter l'ensemble du processus d'ajout et de suppression de commentaires en utilisant Patch JSON . Données de printemps REST a ajouté prise en charge de cela dans la dernière version candidate de la version 2.2 à venir.

53
Oliver Drotbohm

Il existe 2 types de mappage Association et Composition. En cas d'association, nous avons utilisé le concept de table de jointure comme

Employé - 1 à n-> Département

Donc, 3 tables seront créées dans le cas d'un employé d'association, département, employé_département

Il vous suffit de créer EmployeeRepository dans votre code. En dehors de cette cartographie devrait être comme ça:

class EmployeeEntity{

@OnetoMany(CascadeType.ALL)
   private List<Department> depts {

   }

}

Depatment Entity ne contiendra pas de mappage pour la clé étrangère ... alors maintenant, lorsque vous allez essayer la demande POST) pour ajouter un employé avec département dans une demande json unique, elle sera ajoutée ....

2
Naveen Goyal

J'ai fait face au même scénario et j'ai dû supprimer la classe de référentiel pour la sous-entité, car j'ai utilisé le mappage un à plusieurs et extraire des données via l'entité principale elle-même. Maintenant, je reçois toute la réponse avec des données.

1
Selva

Pour le mappage oneToMany, créez simplement un POJO pour la classe que vous souhaitez mapper, ainsi qu'une annotation @OneToMany, et en interne, il sera mappé sur cet identifiant de table.

En outre, vous devez implémenter l'interface Serializable avec la classe dans laquelle vous récupérez les données.

0
Sunny Chaurasia