为什么我从 Hibernate 多对多关系(外键约束)中得到 java.sql.SQLIntegrityConstraintViolationException
Why do I get a java.sql.SQLIntegrityConstraintViolationException from a Hibernate many to many relation (foreign key constraint)
我有 tbl_books
,其中有 m2m 和 tbl_author
。我想保存一本书及其作者。如果我不包含作者列表,我可以保存这本书,但我应该如何将作者保存到书中?我是否需要创建 tbl_book_authors table 才能实现此目的?
{
"title": "a new book",
"publisher": {
"id": 7
},
"authors": [
{
"id": 3
}
]
}
Book.java
...
@NoArgsConstructor
@Entity(name="Book")
@Table(name="tblBook")
public class Book {
@Id
@Column(name = "id", unique = true, nullable = false)
private int id;
private String title;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "pub_id", nullable = false)
private Publisher publisher;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "tblBookAuthors",
joinColumns = { @JoinColumn(name = "bookId") },
inverseJoinColumns = { @JoinColumn(name = "authorId") })
private Set<Author> authors = new HashSet<>();
...
author.java
...
@NoArgsConstructor
@Entity(name="Author")
@Table(name="tblAuthor")
public class Author {
@Id
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@JsonBackReference
@ManyToMany(mappedBy = "authors")
Set<Book> books;
...
日志
Book{id=0, title='a new book', publisher=Publisher{id=7, name='null', address='null', phone='null', books=null}, authors=[Author{id=3, name='null', books=null}]}
Hibernate: select publisher_.id, publisher_.address as address2_4_, publisher_.name as name3_4_, publisher_.phone as phone4_4_ from tbl_publisher publisher_ where publisher_.id=?
Hibernate: insert into tbl_book (pub_id, title, id) values (?, ?, ?)
Hibernate: insert into tbl_book_authors (book_id, author_id) values (?, ?)
2021-11-27 18:49:06.643 WARN 8704 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1452, SQLState: 23000
2021-11-27 18:49:06.643 ERROR 8704 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : Cannot add or update a child row: a foreign key constraint fails (`library`.`tbl_book_authors`, CONSTRAINT `fk_tbl_book_authors_tbl_book1` FOREIGN KEY (`book_id`) REFERENCES `tbl_book` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
2021-11-27 18:49:06.644 INFO 8704 --- [nio-8080-exec-7] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
2021-11-27 18:49:06.663 ERROR 8704 --- [nio-8080-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`library`.`tbl_book_authors`, CONSTRAINT `fk_tbl_book_authors_tbl_book1` FOREIGN KEY (`book_id`) REFERENCES `tbl_book` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
您没有在 Book
实体中自动增加主键,并且您在 JSON OBJECT
中没有为 id
插入任何内容,因此如果您不插入,它会自动插入 0
值id
列中的任何 id,因为您传递了 nullable = false
.
为自增主键输入@GeneratedValue(strategy = GenerationType.IDENTITY)
。
public class Book {
@Id
@Column(name = "id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
...
...
}
我有 tbl_books
,其中有 m2m 和 tbl_author
。我想保存一本书及其作者。如果我不包含作者列表,我可以保存这本书,但我应该如何将作者保存到书中?我是否需要创建 tbl_book_authors table 才能实现此目的?
{
"title": "a new book",
"publisher": {
"id": 7
},
"authors": [
{
"id": 3
}
]
}
Book.java
...
@NoArgsConstructor
@Entity(name="Book")
@Table(name="tblBook")
public class Book {
@Id
@Column(name = "id", unique = true, nullable = false)
private int id;
private String title;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "pub_id", nullable = false)
private Publisher publisher;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "tblBookAuthors",
joinColumns = { @JoinColumn(name = "bookId") },
inverseJoinColumns = { @JoinColumn(name = "authorId") })
private Set<Author> authors = new HashSet<>();
...
author.java
...
@NoArgsConstructor
@Entity(name="Author")
@Table(name="tblAuthor")
public class Author {
@Id
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@JsonBackReference
@ManyToMany(mappedBy = "authors")
Set<Book> books;
...
日志
Book{id=0, title='a new book', publisher=Publisher{id=7, name='null', address='null', phone='null', books=null}, authors=[Author{id=3, name='null', books=null}]}
Hibernate: select publisher_.id, publisher_.address as address2_4_, publisher_.name as name3_4_, publisher_.phone as phone4_4_ from tbl_publisher publisher_ where publisher_.id=?
Hibernate: insert into tbl_book (pub_id, title, id) values (?, ?, ?)
Hibernate: insert into tbl_book_authors (book_id, author_id) values (?, ?)
2021-11-27 18:49:06.643 WARN 8704 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1452, SQLState: 23000
2021-11-27 18:49:06.643 ERROR 8704 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : Cannot add or update a child row: a foreign key constraint fails (`library`.`tbl_book_authors`, CONSTRAINT `fk_tbl_book_authors_tbl_book1` FOREIGN KEY (`book_id`) REFERENCES `tbl_book` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
2021-11-27 18:49:06.644 INFO 8704 --- [nio-8080-exec-7] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
2021-11-27 18:49:06.663 ERROR 8704 --- [nio-8080-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`library`.`tbl_book_authors`, CONSTRAINT `fk_tbl_book_authors_tbl_book1` FOREIGN KEY (`book_id`) REFERENCES `tbl_book` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
您没有在 Book
实体中自动增加主键,并且您在 JSON OBJECT
中没有为 id
插入任何内容,因此如果您不插入,它会自动插入 0
值id
列中的任何 id,因为您传递了 nullable = false
.
为自增主键输入@GeneratedValue(strategy = GenerationType.IDENTITY)
。
public class Book {
@Id
@Column(name = "id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
...
...
}