2017-11-17 14 views
7

Trong dự án của tôi, tôi có hai mô hình miền. Một phụ huynh và một thực thể con. Phụ huynh tham khảo danh sách các trẻ em. (ví dụ: Bài đăng và Nhận xét) Cả hai thực thể đều có các giao diện JPA CrudRepository<Long, ModelClass> JPA dữ liệu vào mùa xuân được hiển thị dưới dạng @RepositoryRestResourceCách tạo thực thể cha mẹ mới tham chiếu đến thực thể con hiện có trong phần còn lại của dữ liệu vào mùa xuân/HATEOAS

Các hoạt động HTTP GET và PUT hoạt động tốt và trả về HATEOS đại diện tốt đẹp của các mô hình này.

Bây giờ tôi cần điểm cuối REST đặc biệt "tạo Phụ huynh mới tham chiếu một quặng hơn đã tồn tại thực thể con". Tôi muốn đăng tài liệu tham khảo cho trẻ em như một văn bản/uri-list mà tôi vượt qua trong cơ thể của các yêu cầu như thế này:

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 

Làm thế nào để thực hiện phần còn lại thiết bị đầu cuối này? Đây là những gì tôi đã cố gắng cho đến nay:

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

} 

Reference/liên quan https://github.com/spring-projects/spring-hateoas/issues/292

+0

Lưu ý: Tôi biết cách tôi có thể thêm các yếu tố vào danh sách trẻ em thông qua triển lãm điểm cuối nghỉ ngơi mùa xuân-ghét ed bởi RepositoryRestResource. Ở đó tôi có thể tạo mối quan hệ con parnet qua POSTing text/uri-list như mô tả ở đây: https://stackoverflow.com/questions/26259474/how-to-add-elements-in-a-many-to-many-relationship -via-springs-repositoryrestr? rq = 1 Nhưng tôi muốn biết làm thế nào tôi làm điều đó trong điểm cuối còn lại tùy chỉnh của riêng tôi. – Robert

+0

Có khá nhiều câu hỏi tương tự như thế này. Nhưng trường hợp đặc biệt của tôi là: Tôi muốn tạo một thực thể cha mẹ _NEW_, nó sẽ được liên kết với quyền con đã được _EXISTING_. – Robert

+0

Tôi hơi bối rối nhưng làm thế nào một đứa trẻ có thể tồn tại trước cha mẹ? Nó giống như bạn tạo một bình luận cho một bài viết mà chưa tồn tại. Thông thường, bạn cũng cố gắng tránh động từ trong điểm cuối tài nguyên vì nó cung cấp một số loại RPC mùi cho điểm cuối, mặc dù REST nó không thực sự quan trọng nếu nó có hay không. –

Trả lời

2

Có một vấn đề liên quan trên một mặt lưu ý, rằng người ta cũng cần phải đưa vào tài khoản: Khi tôi muốn lưu phụ huynh thực thể, sau đó tôi không muốn chạm, lưu hoặc thay đổi thực thể con hiện có theo bất kỳ cách nào. Đây không phải là dễ dàng trong JPA. Bởi vì JPA cũng sẽ (cố gắng) tồn tại thực thể con phụ thuộc. Điều này không thành công với trường hợp ngoại lệ:

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

Để phá vỡ điều đó, bạn phải hợp nhất thực thể con vào transactin của cuộc gọi save() JPA. Cách duy nhất tôi tìm thấy có cả hai thực thể trong một giao dịch là tạo một @Services riêng biệt được đánh dấu là @Transactional. Có vẻ như hoàn thành quá mức cần thiết và quá tải.

Đây là mã của tôi:

PollController.java // điểm cuối tùy chỉnh REST cho các entiy PHỤ HUYNH

@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 // để xử lý giao dịch

@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; 
} 
Các vấn đề liên quan