在SpringJPA的多对多关系中添加现有实体而不是创建新实体

aurhwmvo  于 2023-02-19  发布在  Spring
关注(0)|答案(1)|浏览(133)

我有一个Book实体和Author实体,它们之间有多对多的关系。我有一本书是这样的:(作者A在数据库中的id=1,我使用@GeneratedValue(策略= GenerationType.IDENTITY),所以我不想添加id)

{
  "id": 1,
  "name": "Spring Boot 1"
  "authors": [
     {
        "name": "A"
     }
  ]
}

然后我再创作一本这样的书

{
  "id": 2,
  "name": "Spring Boot 2"
  "authors": [
     {
        "name": "A"
     },
     {
        "name": "B"
     }
  ]
}

问题是Spring JPA将在数据库中创建另一个id=2作者“A”和id=3作者“B”。
我想要的是JPA使用现有作者“A”并创建一个作者“B”,id = 2

书本

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "book")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column
    private String name;
    @Column
    private double price;
    @ManyToMany(
            cascade = CascadeType.ALL,
            fetch = FetchType.LAZY
    )
    @JoinTable(
            name = "book_author",
            joinColumns = @JoinColumn(name = "book_id"),
            inverseJoinColumns = @JoinColumn(name = "author_id")
    )
    @JsonIgnoreProperties("books")
    private List<Author> authors = new ArrayList<>();
}

图书服务

@Service

public class BookService {
    @Autowired
    BookRepository bookRepository;

    public List<Book> getAllBook() {
        return bookRepository.findAll();
    }

    public Book saveBook (Book book) {
        return bookRepository.save(book);
    }

    public void deleteBook(Long id) {
        bookRepository.deleteBookById(id);
    }
}

图书管理员

@RestController
@RequestMapping("/book")
public class BookController {
    @Autowired
    BookService bookService;
    @GetMapping
    public ResponseEntity<List<Book>> getAllBook() {
        return new ResponseEntity<List<Book>>(bookService.getAllBook(), HttpStatus.OK);
    }
    @PostMapping
    public ResponseEntity<Book> saveBook(@RequestBody Book book) {
        return new ResponseEntity<Book>(bookService.saveBook(book), HttpStatus.CREATED);
    }
}

作者

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "author")
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column
    private String name;

    @ManyToMany(mappedBy = "authors", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JsonIgnoreProperties("authors")
    private List<Book> books = new ArrayList<>();
}

AuthorService和AuthorController类似于书本
是否有任何注解或查询可用于修复此问题??或者最有效的方法是什么?

我不想使用下面的解决方案,因为我认为JPA中有一个解决方案比这个更短、更高效,但我不知道
我使用ChatGPT演示了此方法

public ResponseEntity<Book> createBook(@RequestBody Book book) {
        for (Author author : book.getAuthors()) {
            Optional<Author> existingAuthor = authorRepository.findOne(
                Example.of(author, ExampleMatcher.matching().withIgnorePaths("id"))
            );
            if (existingAuthor.isPresent()) {
                book.addAuthor(existingAuthor.get());
            }
        }
        Book savedBook = bookService.save(book);
        return ResponseEntity.created(URI.create("/books/" + savedBook.getId())).body(savedBook);
    }
gz5pxeao

gz5pxeao1#

JPA如何知道是否有两个作者同名?它不能。
如果你想“重用”一个现有的作者,那么你必须自己找到并设置它。
一个小提示,不要将数据库模型中的类用于DTO。

相关问题