@Entity @SuppressWarnings("serial") public class Author extends CommonVersionEntity { private Set<Book> bookSet = new HashSet<Book>(); @ManyToMany @JoinTable(name = "author_book", joinColumns = { @JoinColumn(name = "author_id") }, inverseJoinColumns = { @JoinColumn(name = "book_id") }, uniqueConstraints = @UniqueConstraint(columnNames = { "author_id", "book_id" })) @ForeignKey(name = "author_book_fk", inverseName = "book_author_fk") public Set<Book> getBookSet() { return bookSet; } public void setBookSet(Set<Book> bookSet) { this.bookSet = bookSet; } } @Entity @SuppressWarnings("serial") public class Book extends CommonVersionEntity { private Set<Author> authorSet = new HashSet<Author>(); @ManyToMany(mappedBy = "bookSet") public Set<Author> getAuthorSet() { return authorSet; } public void setAuthorSet(Set<Author> authorSet) { this.authorSet = authorSet; } }
Author 是 owner side,Book 是 inverse side,join table 為 author_book。
遇到的問題是,當直接刪除一筆 Book 時,會發生以下的 error:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`db`.`author_book`, CONSTRAINT `book_author_fk` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`))
簡單說,就是因為 Book 是 inverse side ,所以對 Book 做的任何操作都不會反應到 Author 與 Book 的關聯上,也就是 join table author_book,所以導致 author_book上的 book_author_fk 發出抗議,因為 Book 被刪除,而該 Book id 還留在 author_book 上。
如果單純將 Author 上的 @ForeignKey 拿掉,那會造成 Book 順利刪除,但是該 Book id 還留在 author_book 上,導致下次載入 Author 時發生錯誤,當然可以將錯就錯的在 public Set<Book> getBookSet() { ... } 加上 @NotFound(action = NotFoundAction.IGNORE) 來迴避這樣的問題,唯一的後果就是在 author_book 留下一堆垃圾資料。
不然就是得在刪除 Book 時多做一些事情:
Book obj = this.getBook(id); for (Author author : obj.getAuthorSet()) { author.getBookSet().remove(obj); } this.getHibernateTemplate().delete(obj);將 Book 的每位 Author 找出來,再從 Author 這個 owner side 去移除與該 Book 的關聯。
沒有留言:
張貼留言