SpringData REST에서 @OneToMany 하위 리소스 연관 게시


103

현재 SpringData REST를 사용하는 Spring Boot 애플리케이션이 있습니다. 다른 도메인 엔터티와 관계 가있는 도메인 엔터티 Post가 있습니다 . 이러한 클래스는 다음과 같이 구성됩니다.@OneToManyComment

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

SpringData REST JPA 저장소는 다음의 기본 구현입니다 CrudRepository.

PostRepository.java :

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

CommentRepository.java :

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

애플리케이션 진입 점은 표준의 간단한 Spring Boot 애플리케이션입니다. 모든 것이 구성 재고입니다.

Application.java

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

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

모든 것이 올바르게 작동하는 것 같습니다. 응용 프로그램을 실행하면 모든 것이 올바르게 작동하는 것처럼 보입니다. 다음 http://localhost:8080/posts과 같이 새 Post 객체를 게시 할 수 있습니다 .

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

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

그러나 GET을 수행 http://localhost:8080/posts/1/comments하면 빈 개체가 {}반환되고 동일한 URI에 주석을 게시하려고하면 HTTP 405 Method Not Allowed가 표시됩니다.

Comment자원 을 만들고 이것과 연결 하는 올바른 방법은 무엇입니까 Post? http://localhost:8080/comments가능한 경우 직접 게시하는 것을 피하고 싶습니다 .


9
7 일 후에도 여전히 운이 없습니다. 이 동작을 작동시키는 방법을 아는 사람이 있으면 알려주십시오. 감사!
ccampo 2014-08-22

@RepositoryRestResource 또는 컨트롤러를 사용하고 있습니까? 그 코드를 보는 것도 도움이 될 것입니다.
Magnus Lassi 2014 년

답변:


47

먼저 댓글을 게시해야하며 댓글을 게시하는 동안 연관 게시물 엔티티를 만들 수 있습니다.

다음과 같이 보일 것입니다.

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

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

완벽하게 잘 작동합니다.


2
이것은 나를 위해 일했습니다. author.post쓰기 가능한지 확인하십시오 (예 : setter 또는 @JsonValue주석을
가짐

1
댓글을 한 게시물에서 다른 게시물로 이동하는 것과 같이 패치 요청에서도 작동해야합니까?
aycanadal

2
이것은 내 (대단히) 선호하는 접근 방식이지만 나를 위해 작동하지 않는 것 같습니다. :( 주석을 생성하지만 해결 테이블 (POST_COMMENTS)에 행을 생성하지 않습니다. 해결 방법에 대한 제안 사항이 있습니까?
banncee

3
장소에 주소가 있어야하고 주소가 장소와 연결되어야하는 장소 및 주소 엔티티와 같은 시나리오에 대한 접근 방식은 무엇입니까? 내 말은 ... 아무것에도 할당되지 않을 수있는 고아 주소를 만들지 않으려면? 아마 틀렸을 수도 있지만 클라이언트 앱은 데이터베이스 내에서 일관성을 유지하는 책임이 없어야합니다. 나는 클라이언트 앱이 주소를 생성하고 장소에 확실히 할당하는 것에 의존 할 수 없습니다. 불일치를 피할 수 있도록 실제 리소스 생성과 함께 하위 리소스 (이 경우 주소 엔터티)를 게시하는 방법이 있습니까 ??
apostrophedottilde

2
나는 이것을 시도 하지만 ( 여기 참조 ) 어떤 이유로 연결이 아닌 리소스 만 생성됩니다.
displayname

55

이미 post URI 및 연관 자원의 URI를 발견했다고 가정하면 ( $association_uri다음에 있는 것으로 간주 ) 일반적으로 다음 단계를 수행합니다.

  1. 댓글을 관리하는 컬렉션 리소스를 확인하세요.

    curl -X GET http://localhost:8080
    
    200 OK
    { _links : {
        comments : { href : "…" },
        posts :  { href : "…" }
      }
    }
  2. 리소스에 대한 comments링크와 POST데이터를 따르십시오 .

    curl -X POST -H "Content-Type: application/json" $url 
    {  // your payload // … }
    
    201 Created
    Location: $comment_url
  3. PUT연관 URI에 a 를 발행하여 게시물에 댓글을 지정하십시오 .

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

마지막 단계에서의 사양에 따라 text/uri-list주석을 식별하는 여러 URI를 줄 바꿈으로 구분하여 제출하여 한 번에 여러 주석을 할당 할 수 있습니다.

일반적인 디자인 결정에 대한 몇 가지 추가 정보. 게시물 / 댓글 예는 일반적으로 난에서 백 참조를 피할 것 수단 집계에 대한 좋은 예입니다 Comment받는 사람 Post또한 피 CommentRepository를 완전히합니다. 주석에 자체 수명주기가없는 경우 (일반적으로 구성 스타일 관계가 아님) 주석을 직접 인라인으로 렌더링하고 주석을 추가하고 제거하는 전체 프로세스를 다음을 사용하여 처리 할 수 ​​있습니다. JSON 패치 . SpringData REST는 향후 버전 2.2의 최신 릴리스 후보에서 이에 대한 지원을 추가했습니다 .


4
여기에 아래로 투표 한 유권자들로부터 관심이 있습니다. 투표 이유는 무엇입니까?).
Oliver Drotbohm 2014 년

3
나는 아래로 투표 한 사람들에 대해 잘 모르겠습니다 ... 나는 그것을 할 평판조차도 가지고 있지 않습니다! 내가 게시물에 댓글을 삽입하는 것을 반드시 좋아하지 않는 이유는 단일 게시물에 대해 수천 개의 댓글이있을 때 (가능성이 낮은) 시나리오를 고려하기 때문입니다. 게시물의 내용에 액세스하고 싶을 때마다 댓글 전체를 가져 오는 대신 댓글 모음을 페이지로 매길 수 있기를 바랍니다.
ccampo 2014 년

25
댓글을 게시하는 가장 직관적 인 방법은 localhost : 8080 / posts / 1 / comments에 POST를 만드는 입니다. 가장 간단하고 의미있는 방법이 아닙니까? 동시에 전용 주석 저장소를 사용할 수 있어야합니다. 이것을 허용하지 않는 것이 봄 또는 HAL 표준입니까?
aycanadal

4
@OliverGierke 이것이 여전히 권장 / 유일한 방법입니까? 자식이 nullable이 아닌 경우 ( @JoinColumn(nullable=false))? 먼저 자식을 POST 한 다음 부모 연결을 PUT / PATCH 할 수 없습니다.
JW Lim

2
Spring Data Rest로 만든 API 사용에 대한 가이드가 있습니까? 2 시간 동안 검색했는데 아무것도 찾지 못했습니다. 감사합니다!
Skeeve

2

매핑 연결 및 구성에는 두 가지 유형이 있습니다. 연관의 경우 조인 테이블 개념을 다음과 같이 사용했습니다.

직원 --1에서 n-> 부서

따라서 Association Employee, Department, Employee_Department의 경우 3 개의 테이블이 생성됩니다.

코드에서 EmployeeRepository를 생성하기 만하면됩니다. 그 매핑을 제외하고는 다음과 같아야합니다.

class EmployeeEntity{

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

   }

}

Depatment Entity는 forign 키에 대한 매핑을 포함하지 않으므로 이제 단일 json 요청에서 Department와 Employee를 추가하기위한 POST 요청을 시도하면 추가됩니다 ....


1

나는 동일한 시나리오에 직면했고 일대 다 매핑을 사용하고 주 엔티티 자체를 통해 데이터를 가져 왔기 때문에 하위 엔티티에 대한 저장소 클래스를 제거해야했습니다. 이제 데이터로 전체 응답을 받고 있습니다.


1
당신이 말하는이 일은 쉽게
예측할

0

oneToMany 매핑의 경우 매핑하려는 해당 클래스에 대한 POJO와 @OneToMany 주석을 작성하면 내부적으로 해당 테이블 ID에 매핑됩니다.

또한 데이터를 검색하는 클래스에 Serializable 인터페이스를 구현해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.