简体   繁体   English

Spring数据休息POSTT与ManyToMany关系的新项目

[英]Spring data rest POSTing a new item with ManyToMany relationship

I have two entities: Actor and Movie. 我有两个实体:演员和电影。 Between these two exists a ManyToMany relationship (because and Actor can join more than one Movie and in a Movie you can see more than one Actor). 在这两者之间存在一个ManyToMany关系(因为和Actor可以连接多个Movie,而在Movie中你可以看到多个Actor)。 On my Spring Data Rest API I have the following endpoints: 在我的Spring Data Rest API上,我有以下端点:

http://host:port/movies
http://host:port/actors

Now suppose I would create a new actor from the movie page. 现在假设我将从电影页面创建一个新的actor。 My client will submit a (single) POST request with the actor information and the relationship with the movie. 我的客户端将提交一个(单个)POST请求,其中包含演员信息以及与电影的关系。 I tried with something like the following (a new actor for the movie with id 1): 我尝试了类似下面的内容(id为1的电影的新演员):

{ 
  "name": "Leonardo Di Caprio",
  "movies": [ "http://host:port/movies/1" ]
}

Spring API replies with a 201 Created, so the format and the movie URI are fine. Spring API回复201 Created,因此格式和电影URI都很好。 When I query API or DB for the actor, I discover that the actor has been created but the relationship does not exists. 当我为actor查询API或DB时,我发现已经创建了actor,但关系不存在。

I already know that you should make two requests ( one to create the actor and one to create the relationship ) for ManyToMany relationships with Spring data rest. 我已经知道你应该为SpringTamMany与Spring数据休息的关系做两个请求(一个用于创建actor,一个用于创建关系)。 I'm asking here if there is a way to create both with a single request (like for OneToMany/ManyToOne or OneToOne relationships. 我在这里问是否有办法用单个请求创建两者(比如OneToMany / ManyToOne或OneToOne关系)。

Actor class 演员班

@Entity
public class Actor {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String name;

    @ManyToMany(mappedBy = "actors")
    private List<Movie> movies;

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Movie> getMovies() {
        return movies;
    }

    public void setMovies(List<Movie> movies) {
        this.movies = movies;
    }
}

Movie Class 电影课

@Entity
public class Movie {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected long id;

    protected String title;

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    protected List<Actor> actors;

    public long getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<Actor> getActors() {
        return actors;
    }

    public void setActors(List<Actor> actors) {
        this.actors = actors;
    }

}

For both entities, I have standard repositories: 对于这两个实体,我有标准存储库:

@Repository
public interface ActorRepository extends PagingAndSortingRepository<Actor, Long> {
}

UPDATE UPDATE

The behaviour that I was facing was due to how JPA handles ManyToMany relationships. 我面临的行为是由于JPA如何处理ManyToMany关系。 In this thread there is a clever explanation on how to handle bidirectional associations with JPA and REST. 在这个主题中,有一个关于如何处理与JPA和REST的双向关联的聪明解释。

I can solve my problem with one of these two options: 我可以用以下两个选项之一解决我的问题:

A - Doing two POST requests, one on A - 执行两个POST请求,一个打开

http://host:port/actors 

to persist the new Actor and one on the 坚持新的演员和一个人

http://host:port/movies/{id}/actors 

as the following: 如下:

...                                              |
Content-Type: text/uri-list                      | headers
...                                              |

http://host:port/actors/{id-of-the-new-actor}    | body

to persist the association between the new actor and the movie. 坚持新演员和电影之间的联系。

B - Doing only one POST request on B - 仅执行一个POST请求

http://host:port/actors 

(as I described at the beginning of the question) but modifying the setMovies method in the Actor class (as described in the thread I cited). (正如我在问题开头所描述的那样)但修改了Actor类中的setMovies方法(如我引用的主题中所述)。

First create the resources : create the actor resource : 首先创建资源:创建actor资源:

curl -i -X POST -H "Content-Type:application/json"
    -d "{\"name\":\"Leonardo Di Caprio\"}" http://host:port/actors

then create the movies : 然后制作电影:

curl -i -X POST -H "Content-Type:application/json"
  -d "{\"title\":\"Titanic\"}" http://host:port/movies

finaly create the association (supposing http://host:port/actors/1 is dicaprio uri): 最终创建关联(假设http:// host:port / actors / 1是dicaprio uri):

curl -i -X PUT -H "Content-Type:text/uri-list"
  --data-binary @movies.txt http://host:port/actors/1/movies

with movies.txt containing the movie's uris, each on a separate line: 包含电影的uris的movies.txt,每个都在一个单独的行上:

http://host:por/movies/1
http://host:por/movies/2

follow this useful link 按照这个有用的链接

For a many to many you would need a table that sits between and Actor and Movies table with the id of both. 对于多对多,您需要一个位于Actor和Movies表之间的表,其id为两者。

Table structure may look like this? 表结构可能如下所示? CREATE TABLE `ActorMovies` ( `actorId` INT NOT NULL, `movieId` INT NOT NULL, PRIMARY KEY (`ActorId`, `MoviesId`));

Then the joining of the tables looks like this 然后表的连接看起来像这样

@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name = "ActorMovies", joinColumns = {
    @JoinColumn(name = "movieId", nullable = false, updatable = false) },inverseJoinColumns = { @JoinColumn(name = "actorId",nullable = false, updatable = false) })
    public Set<Category> getActors() {
        return this.actors;
    }

Many to many code example 许多代码示例

https://www.mkyong.com/hibernate/hibernate-many-to-many-relationship-example-annotation/ https://www.mkyong.com/hibernate/hibernate-many-to-many-relationship-example-annotation/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM