2017-11-17 2 views
7

내 프로젝트에는 두 개의 도메인 모델이 있습니다. 부모와 자식 개체. 부모는 하위 항목의 목록을 참조합니다. (예 : 게시 및 설명) 두 엔티티 모두 @RepositoryRestResource봄 데이터 rest/HATEOAS에서 기존의 자식 엔티티를 참조하는 새로운 상위 엔티티를 만드는 방법

HTTP GET 및 PUT 작업이 정상적으로 작동하고 이러한 모델의 멋진 HATEOS 표현을 반환하는 스프링 데이터 JPA CrudRepository<Long, ModelClass>이 있습니다.

이제 특별한 REST 엔드 포인트가 필요합니다. "이 이미 존재하는 하위 엔티티를 참조하는 새 상위를 만듭니다."

POST http://localhost:8080/api/v1/createNewParent 
HEADER 
    Content-Type: text/uri-list 
HTTP REQUEST BODY: 
    http://localhost:8080/api/v1/Child/4711 
    http://localhost:8080/api/v1/Child/4712 
    http://localhost:8080/api/v1/Child/4713 

가 어떻게이 나머지 엔드 포인트를 구현합니까 : 나는이 같은 요청의 본문에 통과 텍스트/URI-목록으로 아이들에 대한 참조를 게시하고 싶습니다? 이것은 내가 지금까지 뭘하려 : 관련

@Autowired 
ParentRepo parentRepo // Spring Data JPA repository for "parent" entity 


@RequestMapping(value = "/createNewParent", method = RequestMethod.POST) 
public @ResponseBody String createNewParentWithChildren(
    @RequestBody Resources<ChildModel> childList,       
    PersistentEntityResourceAssembler resourceAssembler 
) 
{ 
    Collection<ChildModel> childrenObjects = childList.getContent() 

    // Ok, this gives me the URIs I've posted 
    List<Link> links = proposalResource.getLinks(); 

    // But now how to convert these URIs to domain objects??? 
    List<ChildModel> listOfChildren = ... ???? ... 

    ParentModel newParnet = new ParentModel(listOfChildren) 
    parentRepo.save(newParent) 

} 

참조/ https://github.com/spring-projects/spring-hateoas/issues/292

+0

참고 : 스프링 - hateoas 휴식 종점 노출을 통해 하위 요소 목록에 요소를 추가하는 방법을 알고 있습니다. RepositoryRestResource에 의해 편집됩니다. 여기에 설명 된대로 POSTing text/uri-list를 통해 parnet 자식 관계를 만들 수 있습니다. https://stackoverflow.com/questions/26259474/how-to-add-elements-in-a-many-to-many-relationship -via-springs-repositoryrestr? rq = 1하지만 내 자신의 사용자 지정 끝점에서 내가 어떻게하는지 알고 싶습니다. – Robert

+0

이렇게 아주 비슷한 질문이 많이 있습니다. 하지만 특별한 경우입니다 : 이미 _EXISTING_ 하위 항목에 링크 된 _NEW_ 상위 항목을 만들고 싶습니다. – Robert

+0

조금 혼란 스럽지만 부모 앞에서 어떻게 아이가 존재할 수 있습니까? 그것은 아직 존재하지 않는 게시물에 대한 의견을 작성하는 것과 같습니다. 일반적으로 끝점에 일종의 RPC 냄새를주기 때문에 리소스 끝점에서 동사를 피하려고합니다. 그러나 REST에서는 그것이 존재하는지 여부는 중요하지 않습니다. –

답변

2

보조 노트에 하나의 관련 문제는, 하나는 또한 고려해야 할 필요가있다 : 나는 부모를 저장할 때 엔티티 인 경우 엔 어떤 방식 으로든 기존의 엔티티를 만지거나 저장하거나 변경하고 싶지 않습니다. 이것은 JPA에서 쉽지 않습니다. JPA는 종속 자식 엔티티도 유지하려고합니다. 이 예외와 함께 실패

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: 

것을 회피하기 위해, 당신은() 호출을 저장 JPA의 transactin에 자식 개체를 병합해야합니다. 하나의 트랜잭션에 두 엔티티가 모두있는 유일한 방법은 @Transactional로 표시된 별도의 @Services를 만드는 것입니다. 완전한 잔인한 과오와 같아 보인다. 여기

내 코드입니다 :

PollController.java // 부모 entiy에 대한 사용자 지정 REST 엔드 포인트

@BasePathAwareController 
public class PollController { 

@RequestMapping(value = "/createNewPoll", method = RequestMethod.POST) 
public @ResponseBody Resource createNewPoll(
    @RequestBody Resource<PollModel> pollResource, 
    PersistentEntityResourceAssembler resourceAssembler 
) throws LiquidoRestException 
{ 
    PollModel pollFromRequest = pollResource.getContent(); 
    LawModel proposalFromRequest = pollFromRequest.getProposals().iterator().next();    // This propsal is a "detached entity". Cannot simply be saved. 
    //jpaContext.getEntityManagerByManagedType(PollModel.class).merge(proposal);  // DOES NOT WORK IN SPRING. Must handle transaction via a seperate PollService class and @Transactional annotation there. 

    PollModel createdPoll; 
    try { 
    createdPoll = pollService.createPoll(proposalFromRequest, resourceAssembler); 
    } catch (LiquidoException e) { 
    log.warn("Cannot /createNewPoll: "+e.getMessage()); 
    throw new LiquidoRestException(e.getMessage(), e); 
    } 

    PersistentEntityResource persistentEntityResource = resourceAssembler.toFullResource(createdPoll); 

    log.trace("<= POST /createNewPoll: created Poll "+persistentEntityResource.getLink("self").getHref()); 

    return persistentEntityResource; // This nicely returns the HAL representation of the created poll 
} 

PollService.java // 트랜잭션 처리를위한

@Service 
public class PollService { 

    @Transactional // This should run inside a transaction (all or nothing) 
    public PollModel createPoll(@NotNull LawModel proposal, PersistentEntityResourceAssembler resourceAssembler) throws LiquidoException { 
    //===== some functional/business checks on the passed enties (must not be null etc) 
    //[...] 

    //===== create new Poll with one initial proposal 
    log.debug("Will create new poll. InitialProposal (id={}): {}", proposal.getId(), proposal.getTitle()); 
    PollModel poll = new PollModel(); 
    LawModel proposalInDB = lawRepo.findByTitle(proposal.getTitle()); // I have to lookup the proposal that I already have 

    Set<LawModel> linkedProposals = new HashSet<>(); 
    linkedProposals.add(proposalInDB); 
    poll.setProposals(linkedProposals); 

    PollModel savedPoll = pollRepo.save(poll); 

    return savedPoll; 
} 
관련 문제