Obecnie posiadam aplikację Spring Boot używającą Spring Data REST. Mam podmiot domeny Post
, która ma @OneToMany
związek z innym podmiotem domeny Comment
. Klasy te mają następującą strukturę:
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...
}
Comment.java:
@Entity
public class Comment {
@Id
@GeneratedValue
private long id;
private String author;
private String content;
@ManyToOne
private Post post;
// Standard getters and setters...
}
Ich repozytoria Spring Data REST JPA to podstawowe implementacje CrudRepository
:
PostRepository.java:
public interface PostRepository extends CrudRepository<Post, Long> { }
CommentRepository.java:
public interface CommentRepository extends CrudRepository<Comment, Long> { }
Punktem wejścia aplikacji jest standardowa, prosta aplikacja Spring Boot. Wszystko jest skonfigurowane w magazynie.
Application.java
@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
}
Wszystko wydaje się działać poprawnie. Po uruchomieniu aplikacji wszystko wydaje się działać poprawnie. Mogę OPUBLIKOWAĆ nowy obiekt posta, aby http://localhost:8080/posts
:
Ciało:
{"author":"testAuthor", "title":"test", "content":"hello world"}
Wynik w 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"
}
}
}
Jednak gdy wykonuję GET w http://localhost:8080/posts/1/comments
, otrzymuję {}
zwracany pusty obiekt i jeśli spróbuję POSTOWAĆ komentarz do tego samego identyfikatora URI, otrzymuję metodę HTTP 405 niedozwoloną.
Jaki jest właściwy sposób tworzenia Comment
zasobu i kojarzenia go z tym Post
? Chciałbym uniknąć wysyłania postów bezpośrednio do, http://localhost:8080/comments
jeśli to możliwe.
Odpowiedzi:
Najpierw musisz opublikować komentarz, a podczas publikowania komentarza możesz utworzyć jednostkę postów asocjacyjnych.
Powinien wyglądać jak poniżej:
i będzie działać idealnie.
źródło
author.post
można zapisywać (na przykład ustawiając lub@JsonValue
adnotację)Zakładając, że już odkryłeś identyfikator URI wiadomości, a tym samym identyfikator URI zasobu asocjacji (uważany za
$association_uri
poniżej), zazwyczaj wykonuje się następujące kroki:Odkryj komentarze do zarządzania zasobami kolekcji:
Skorzystaj z
comments
linku iPOST
swoich danych do zasobu:Przypisz komentarz do posta, wydając
PUT
identyfikator URI skojarzenia.Zwróć uwagę, że w ostatnim kroku, zgodnie ze specyfikacją
text/uri-list
, możesz przesłać wiele identyfikatorów URI identyfikujących komentarze oddzielone znakiem końca wiersza, aby przypisać wiele komentarzy jednocześnie.Jeszcze kilka uwag na temat ogólnych decyzji projektowych. Przykład postu / komentarzy jest zwykle świetnym przykładem agregacji, co oznacza, że unikałbym odniesienia wstecznego od
Comment
do,Post
a takżeCommentRepository
całkowicie unikałbym . Jeśli komentarze nie mają własnego cyklu życia (czego zwykle nie mają w relacji w stylu kompozycji), wolisz je renderować bezpośrednio w tekście, a cały proces dodawania i usuwania komentarzy można raczej przeprowadzić za pomocą Poprawka JSON . Spring Data REST dodał obsługę tego w najnowszej wersji kandydata na nadchodzącą wersję 2.2.źródło
@JoinColumn(nullable=false)
)? Nie byłoby możliwe najpierw OPUBLIKOWANIE dziecka, a następnie PUT / PATCH powiązanie nadrzędne.Istnieją 2 typy mapowania: asocjacja i kompozycja. W przypadku asocjacji zastosowaliśmy koncepcję łączenia stołu, taką jak
Pracownik - 1 do n-> Dział
W związku z tym zostaną utworzone 3 tabele w przypadku Pracownik Stowarzyszenia, Departament, Dział_Pracownik
Musisz tylko utworzyć EmployeeRepository w swoim kodzie. Poza tym mapowanie powinno wyglądać tak:
Jednostka działu nie będzie zawierała żadnego mapowania dla klucza obcego ... więc teraz, gdy spróbujesz wysłać żądanie POST o dodanie pracownika z działem w pojedynczym żądaniu json, zostanie ono dodane ....
źródło
Zmierzyłem się z tym samym scenariuszem i musiałem usunąć klasę repozytorium dla jednostki podrzędnej, ponieważ użyłem jednego do wielu mapowań i wyciągnąłem dane przez samą jednostkę główną. Teraz otrzymuję całą odpowiedź z danymi.
źródło
W przypadku mapowania oneToMany, po prostu utwórz POJO dla tej klasy, którą chcesz mapować, i adnotację @OneToMany do niej, a wewnętrznie zamapuje to na ten identyfikator tabeli.
Ponadto musisz zaimplementować interfejs Serializable do klasy, dla której pobierasz dane.
źródło