2016-08-20 1 views
3

Ich habe zwei Einheiten: Schauspieler und Film. Zwischen diesen beiden besteht eine ManyToMany-Beziehung (weil und Actor kann mehr als einem Film beitreten und in einem Film können Sie mehr als einen Darsteller sehen). Auf meinem Spring Data REST-API habe ich folgende Endpunkte:Spring Daten Rest POSTing ein neues Element mit ManyToMany Beziehung

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

Nehmen wir nun an würde ich einen neuen Schauspieler aus dem Film-Seite erstellen. Mein Kunde sendet eine (einzelne) POST-Anfrage mit den Informationen zum Akteur und der Beziehung zum Film. Ich habe versucht, mit so etwas wie der folgenden (einem neuen Schauspieler für den Film mit der ID 1):

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

Frühling API antwortet mit einem 201 Erstellt, so dass das Format und der Film URI ist in Ordnung. Wenn ich die API oder DB für den Akteur abfrage, stelle ich fest, dass der Akteur erstellt wurde, aber die Beziehung nicht existiert.

Ich weiß bereits, dass Sie zwei Anforderungen (eine zum Erstellen des Akteurs und eine zum Erstellen der Beziehung) für ManyToMany-Beziehungen mit Spring Datenrest machen sollten. Ich frage hier, ob es einen Weg gibt, beide mit einer einzigen Anfrage zu erstellen (wie für OneToMany/ManyToOne oder OneToOne Beziehungen.

Schauspieler Klasse

@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-Klasse

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

} 

Für beide Entitäten, ich habe Standard-Repositories:

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

UPDATE

Das Verhalten, dem ich gegenüberstand, war darauf zurückzuführen, wie JPA ManyToMany-Beziehungen behandelt. In dieser thread gibt es eine kluge Erklärung, wie bidirektionale Assoziationen mit JPA und REST behandelt werden.

ich mein Problem mit einem dieser beiden Optionen lösen:

A - Doing zwei POST-Anfragen, einen auf

http://host:port/actors 

die neuen Schauspieler und einer auf die

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

wie folgt:

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

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

die Verbindung zwischen dem neuen Schauspieler und dem Film bestehen bleiben.

B - tut nur eine POST-Anfrage auf

http://host:port/actors 

(wie ich am Anfang der Frage beschrieben), aber die setMovies Methode in der Actor Klasse Modifizieren (wie in dem Thread I beschrieben zitiert) .

+0

Scheint wie eine seltsame Art, die zugehörigen Filme zu veröffentlichen. Wie sieht die Methodenmethode in Ihrem Ruhe-Controller aus? – ChiefTwoPencils

+0

Ich werde nur einen verknüpften Film veröffentlichen. Auf der Filmseite können Sie Schauspieler für den Film hinzufügen, den Sie gerade sehen. Daher dachte ich, dass es nur die beste Art ist, nur eine Anfrage zu stellen. Sag mir, ob zwei Anfragen (eine für den neuen Schauspieler und eine für die neue Beziehung zwischen Film und Schauspieler) eine bessere Wahl wäre. – Francesco

+0

Eine nette Frage, die unbeantwortet bleibt:/ – EralpB

Antwort

-1

Für eine viel zu viele brauchen Sie einen Tisch, der zwischen und Schauspieler und Filme Tabelle mit der ID von beiden sitzt.

Tabellenstruktur kann so aussehen? CREATE TABLE `ActorMovies` ( `actorId` INT NOT NULL, `movieId` INT NOT NULL, PRIMARY KEY (`ActorId`, `MoviesId`));

Dann sieht das Verbinden der Tabellen wie dies

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

Viele zu viele Codebeispiel

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

+1

Ok, aber es ist nicht der Punkt. Spring Data (Hibernate, um ehrlich zu sein), erstellt bereits automatisch eine Join-Tabelle unter der Haube, um die n-n-Beziehung zu verarbeiten. Meine Frage ist: Warum erstellt die angefügte JSON-Anfrage einen neuen Actor und erzeugt nicht die Beziehung zwischen dem Actor und dem Movie? Ich habe einen Fehler im Anfrageformat gemacht? Ich denke, das ist nicht der Fall, sonst hätte ich eine 400 Bad Request Antwort erhalten. Also, sollte ich zwei Anfragen stellen, eine für den neuen Darsteller und eine für die Beziehung? – Francesco

1

zuerst die Ressourcen erstellen: der Schauspieler Ressource erstellen:

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

dann erzeugen die Filme:

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

finaly die Assoziation schaffen (unter der Annahme http://host:port/actors/1 dicaprio uri ist):

mit movies.txt des Films URIs enthält, die jeweils auf einer separaten Zeile:

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

folgen dieser nützlichen link

+0

Curl ist die Befehlszeile (normalerweise). Der Frühling wurde angefordert. – Gibolt

Verwandte Themen