英文:
Removing Non-Owner Of relation with JPQL removes relation too
问题
entityManager.remove() VS JPQL DELETE Query
我知道关系的一侧是所有者,而另一侧,用mapped by
标记的一侧是非所有者。
关系在数据库中以所有者的持久性保存,并随着其移除而移除。
我知道移除非所有者一侧不会删除关系。
参见此链接
到目前为止都很好。
根据我的经验,使用JPQL查询来删除非所有者一侧的关系也会移除关系。对我来说不太清楚为什么!? 有没有令人信服的解释?
下面的代码片段显示了我用概念进行测试的测试案例:
非所有者
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
@ManyToMany(mappedBy = "books")
private Set<Author> authors;
}
所有者:
@Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToMany
private Set<Book> books;
}
测试1
public void persistingRelationOwnerPersistsRelationSuccessfully(){
Book book = new Book("nonOwner");
entityManager.persist(book);
Author author = new Author("owner", new HashSet<>(Arrays.asList(book)));
entityManager.persist(author);
entityManager.flush();
}
日志:
Hibernate: insert into book (title, id) values (?, ?)
Hibernate: insert into author (name, id) values (?, ?)
Hibernate: insert into author_books (authors_id, books_id) values (?, ?)
测试2
public void removingRelationOwnerRemovesRelationSuccessfully(){
// 持久化图书和作者
entityManager.remove(author);
entityManager.flush();
}
日志:
Hibernate: insert into book (title, id) values (?, ?)
Hibernate: insert into author (name, id) values (?, ?)
Hibernate: insert into author_books (authors_id, books_id) values (?, ?)
Hibernate: delete from author_books where authors_id=?
Hibernate: delete from author where id=?
测试3
public void removingNonOwnerWillThrowException(){
// 持久化图书和作者
entityManager.remove(book);
entityManager.flush();
}
日志:(如预期)
Hibernate: insert into book (title, id) values (?, ?)
Hibernate: insert into author (name, id) values (?, ?)
Hibernate: insert into author_books (authors_id, books_id) values (?, ?)
Hibernate: delete from book where id=?
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
测试4
public void removingNonOwnerWithQueryWillRemoveRelation(){
// 持久化图书和作者
Query query = entityManager.createQuery("delete from Book b where b.title = 'nonOwner'");
System.out.println("affectedRows = " + query.executeUpdate());
}
日志:(意外的行为)
Hibernate: insert into book (title, id) values (?, ?)
Hibernate: insert into author (name, id) values (?, ?)
Hibernate: insert into author_books (authors_id, books_id) values (?, ?)
Hibernate: delete from author_books where (books_id) in (select id from book where title='nonOwner')
Hibernate: delete from book where title='nonOwner'
affectedRows = 1
英文:
entityManager.remove() VS JPQL DELETE Query
I know that one side of relation is owner and the other side, marked with mapped by, is non-owner.
Relation is saved in Database with persistence of owner and removed with removal of it.
I know that removal of non-owner side will not erase relation.
see this link
So far so good.
In my experience, removal on non-owner with JPQL query, removes relation too. It's not clear for me why!? Is there any persuasive explanation?
Code snippets below show my test cases with concept:
Non-Owner
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
@ManyToMany(mappedBy = "books")
private Set<Author> authors;
}
Owner:
@Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToMany
private Set<Book> books;
}
Test 1
public void persistingRelationOwnerPersistsRelationSuccessfully(){
Book book = new Book("nonOwner");
entityManager.persist(book);
Author author = new Author("owner", new HashSet<>(Arrays.asList(book)));
entityManager.persist(author);
entityManager.flush();
}
Log:
Hibernate: insert into book (title, id) values (?, ?)
Hibernate: insert into author (name, id) values (?, ?)
Hibernate: insert into author_books (authors_id, books_id) values (?, ?)
Test 2
public void removingRelationOwnerRemovesRelationSuccessfully(){
//persist book and author
entityManager.remove(author);
entityManager.flush();
}
Log:
Hibernate: insert into book (title, id) values (?, ?)
Hibernate: insert into author (name, id) values (?, ?)
Hibernate: insert into author_books (authors_id, books_id) values (?, ?)
Hibernate: delete from author_books where authors_id=?
Hibernate: delete from author where id=?
Test 3
public void removingNonOwnerWillThrowException(){
//persist book and author
entityManager.remove(book);
entityManager.flush();
}
Log: (As Expected)
Hibernate: insert into book (title, id) values (?, ?)
Hibernate: insert into author (name, id) values (?, ?)
Hibernate: insert into author_books (authors_id, books_id) values (?, ?)
Hibernate: delete from book where id=?
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
Test 4
public void removingNonOwnerWithQueryWillRemoveRelation(){
//persist book and author
Query query = entityManager.createQuery("delete from Book b where b.title = 'nonOwner'");
System.out.println("affectedRows = " + query.executeUpdate());
}
Log: (Unexpected behavior)
Hibernate: insert into book (title, id) values (?, ?)
Hibernate: insert into author (name, id) values (?, ?)
Hibernate: insert into author_books (authors_id, books_id) values (?, ?)
Hibernate: delete from author_books where (books_id) in (select id from book where title='nonOwner')
Hibernate: delete from book where title='nonOwner'
affectedRows = 1
答案1
得分: 1
这可能是一个错误,因为这应该取决于 Book#authors
关联的级联设置,该设置可能会在删除 DML 语句中被忽略。您应该使用一个可重现的示例在 https://hibernate.atlassian.net/ 上记录此问题。
英文:
This might be a bug because this should depend on the cascading setting of the Book#authors
association which might be ignored for a delete DML statement. You should log an issue with a reproducer https://hibernate.atlassian.net/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论