You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data JPA与Hibernate多对多保存冲突问题咨询

Spring Data JPA多对多关联保存重复唯一键异常问题

Book.java 实体代码

public class Book  {

@Id
private int id;

private String title;

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "author_book",
    joinColumns = @JoinColumn(name = "book_id"),
    inverseJoinColumns = @JoinColumn(name = "author_id"))
private Set<Author> authors = new HashSet<>();

// 构造方法、setter、getter、equals和hashCode已省略
// equals和hashCode实现中未包含authors集合

public void addAuthor(Author author) {
    authors.add(author);
    author.getBooks().add(this);
}

Author.java 实体代码

public class Author  {

@Id
private int id; 

private String name;

@Column(unique = true)
private String phoneNumber;

@ManyToMany(mappedBy = "authors")
private Set<Book> books = new HashSet<>();

// 构造方法、setter、getter、equals和hashCode已省略
// equals和hashCode实现中未包含books集合

 public void addBook(Book book) {
    books.add(book);
    book.getAuthors().add(this);
 }

问题场景

当尝试保存关联同一已存在作者的书籍时,抛出唯一键重复异常。

Spring Data JPA测试代码

@Bean
ApplicationRunner applicationRunner(BookRepository bookRepository) {
    return args -> {
        Author a1 = new Author("author1", "phone1");
        Author a2 = new Author("author2", "phone2");
        Author a3 = new Author("author3", "phone3");

        Book b1 = new Book();
        b1.setId("id1");
        b1.setName("book1");
        b1.setAuthors(Set.of(a1, a2));

        Book b2 = new Book();
        b2.setId("id2");
        b2.setName("book2");
        b2.setAuthors(Set.of(a1, a3));

        bookRepository.save(b1);
        bookRepository.save(b2);
    };
}

抛出的异常信息

Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "authors_phone_number_key" Detail: Key (phone_number)=(phone1) already exists.

纯Hibernate执行对比

使用纯Hibernate执行相同逻辑,代码如下:

try (EntityManager em = emf.createEntityManager()) {
        em.getTransaction().begin();

        Author a1 = new Author("author1", "phone1");
        Author a2 = new Author("author2", "phone2");
        Author a3 = new Author("author3", "phone3");

        Book b1 = new Book();
        b1.setId("id1");
        b1.setName("book1");
        b1.setAuthors(Set.of(a1, a2));

        Book b2 = new Book();
        b2.setId("id2");
        b2.setName("book2");
        b2.setAuthors(Set.of(a1, a3));

        em.persist(b1);
        em.persist(b2);

        em.getTransaction().commit(); 
    }

执行结果符合预期:

  • authors表新增3条记录
  • books表新增2条记录
  • author_book关联表新增4条记录

疑问

使用Spring Data JPA时是否遗漏了某些配置?它是否覆盖了Hibernate的默认行为?

内容的提问来源于stack exchange,提问作者Mohammad Ballour

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:47:10