【问题标题】:POSTing oneToMany in a REST call via Spring Boot API通过 Spring Boot API 在 REST 调用中发布 oneToMany
【发布时间】:2019-03-24 21:05:29
【问题描述】:

当我从单个 REST 调用发布以创建图书馆并为图书馆关联图书时遇到问题。图书馆记录已创建,但关联的书籍未创建。 Library 和 Book 具有 oneToMany 关系。 我的 POST 请求和响应如下 -

POST - http://localhost:8080/libraries/

REQUEST BODY
{
    "name":"My Library",
    "books": [
        {"title": "Effective Java", "isbn": "1234"},
        {"title": "Head First Java", "isbn": "5678"}
        ]
}
REPOSNSE 
1

POST 后获取库 - http://localhost:8080/libraries/

[
    {
        "id": 1,
        "name": "My Library",
        "books": [],
        "address": null
    }
]

POST to create Library and add Books GET REQUEST for Libraries

模型

package com.publiclibrary.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import org.springframework.data.rest.core.annotation.RestResource;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@Entity
public class Library {

    @Id
    @GeneratedValue
    private long id;

    @Column
    private String name;

    @OneToMany(mappedBy = "library")
    private List<Book> books;

    @OneToOne
    @JoinColumn(name = "address_id")
    @RestResource(path = "libraryAddress", rel="address")
    private Address address;

    // standard constructor, getters, setters
    public Library(String name) {
        super();
        this.name = name;
    }

}
package com.publiclibrary.domain;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotNull;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
//@Builder
//@AllArgsConstructor
@Entity
public class Book {

    @Id
    @GeneratedValue
    private long id;

    @NotNull
    private String title, isbn;

    @ManyToOne
    @JoinColumn(name="library_id")
    private Library library;    


    @ManyToMany(mappedBy = "books")
    private List<Author> authors;
}

存储库

package com.publiclibrary.repo;

import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

import com.publiclibrary.domain.Book;

@RepositoryRestResource(path = "books", collectionResourceRel = "books")
public interface BookRepository extends PagingAndSortingRepository<Book, Long> {

}
package com.publiclibrary.repo;

import org.springframework.data.repository.CrudRepository;

import com.publiclibrary.domain.Library;

public interface LibraryRepository extends CrudRepository<Library, Long> {
}

服务

package com.publiclibrary.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.publiclibrary.domain.Library;
import com.publiclibrary.repo.LibraryRepository;

@Service
public class LibraryService {

    @Autowired
    LibraryRepository libraryRepository;

    public List<Library> getAllLibrarys() {
        List<Library> librarys = new ArrayList<Library>();
        libraryRepository.findAll().forEach(library -> librarys.add(library));
        return librarys;
    }

    public Library getLibraryById(long id) {
        return libraryRepository.findById(id).get();
    }

    public void saveOrUpdate(Library library) {
        libraryRepository.save(library);
    }

    public void delete(long id) {
        libraryRepository.deleteById(id);
    }
}

REST 控制器

package com.publiclibrary.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.publiclibrary.domain.Library;
import com.publiclibrary.service.LibraryService;

@RestController
public class LibraryController {

    @Autowired
    LibraryService libraryService;

    @GetMapping("/libraries")
    private List<Library> getAllLibrarys() {
        return libraryService.getAllLibrarys();
    }

    @GetMapping("/libraries/{id}")
    private Library getLibrary(@PathVariable("id") int id) {
        return libraryService.getLibraryById(id);
    }

    @DeleteMapping("/libraries/{id}")
    private void deleteLibrary(@PathVariable("id") int id) {
        libraryService.delete(id);
    }

    @PostMapping("/libraries")
    private long saveLibrary(@RequestBody Library library) { 
        libraryService.saveOrUpdate(library);
        return library.getId(); 
    }

}

如何按我的意愿创建图书馆和添加图书?感谢任何帮助!

【问题讨论】:

    标签: java json rest spring-boot one-to-many


    【解决方案1】:

    尝试在图书馆类的书籍集合上添加级联持久化(或者最好只是级联所有)。例如

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "library", cascade = CascadeType.ALL)
    private List<Book> books;
    

    【讨论】:

    • 感谢您在 Book 中创建了记录,但未建立与 Library 的关联(两本书的 library_id 均为 null)。
    • 尝试在 libraryService.saveOrUpdate(library) 之前添加这一行: "if(library.getBooks()!=null) library.getBooks.stream().forEach(b->{ b.setLibrary(库) });"
    【解决方案2】:

    我关注this article 并解决了问题。我明确地处理了解析 JSON 并创建了我的数据对象。此外,我在父(库)类中添加了添加和删除方法,并定义了等号和哈希码,原因在上面的链接中进行了解释。

    我的代码更改如下 -

    图书馆 -

        @OneToMany(mappedBy = "library", cascade = CascadeType.ALL, orphanRemoval = true)
    @JsonIgnoreProperties("library")
    private List<Book> books = new ArrayList<>();
    
    public void addBook(Book book) {
        books.add(book);
        book.setLibrary(this);
    }
    
    public void removeBook(Book book) {
        books.remove(book);
        book.setLibrary(null);
    }
    

    书-

    @JsonIgnoreProperties("books")
    private Library library;    
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Book )) return false;
        return id != null && id.equals(((Book) o).id);
    }
    @Override
    public int hashCode() {
        return 31;
    }
    

    图书馆控制器 -

        @PostMapping("/libraries")
    private long saveLibrary(@RequestBody Map<String, Object> payload) {
        Library library = new Library();
        library.setName(payload.get("name").toString());
    
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> books = (List<Map<String, Object>>) payload.get("books");
        for (Map<String, Object> bookObj : books) {
            Book book = new Book();
            book.setTitle(bookObj.get("title").toString());
            book.setIsbn(bookObj.get("isbn").toString());
            library.addBook(book);
        }
    
        libraryService.saveOrUpdate(library);
    
        return library.getId(); 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-15
      • 2019-01-06
      • 2019-04-23
      • 2014-10-08
      • 2018-10-06
      • 1970-01-01
      • 2016-08-16
      相关资源
      最近更新 更多