如何解决Hibernate left join fetch to soft-deleted entity 映射到@ManyToMany 关联生成无效查询?
我不知道这是 Hiberante 的问题还是我做错了什么。
我试图让这个例子尽可能简单。
我的实体:
Book.java:
@Entity
@Table(name="books")
@sqlDelete(sql="UPDATE books set is_deleted = true where id = ?")
@Where(clause="is_deleted = false")
public class Book implements Serializable {
@Id
@Column(name = "id",updatable = false,nullable = false)
private long id;
@Column (name="is_deleted")
private boolean deleted;
@Column(name="title")
private String title;
@ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
@JoinTable(
name="books_authors",joinColumns = {
@JoinColumn(name="id_books")
},inverseJoinColumns = {
@JoinColumn(name="id_authors")
}
)
private Set<Author> authors = new HashSet<>();
//getters/setters
}
作者.java:
@Entity
@Table(name="autors")
@sqlDelete(sql="UPDATE autors set is_deleted = true where id = ?")
@Where(clause="is_deleted = false")
public class Author implements Serializable {
@Id
@Column(name = "id",nullable = false)
private long id;
@Column(name="name")
private String name;
@Column (name="is_deleted")
private boolean deleted;
@ManyToMany(mappedBy = "authors",fetch = FetchType.LAZY)
private Set<Book> books = new HashSet<>();
//getters/setters
}
底层表:
create table autors (
id int8 not null,is_deleted boolean,name varchar(255),primary key (id)
);
create table books (
id int8 not null,title varchar(255),primary key (id)
);
create table books_authors (
id_books int8 not null,id_authors int8 not null,primary key (id_books,id_authors)
);
alter table if exists books_authors add constraint FK9xru8ocoxufr5eva6atfyfjxh foreign key (id_authors) references autors;
alter table if exists books_authors add constraint FKx5d5025t9ct5kcbwwxm6tipo foreign key (id_books) references books;
数据:
select * from books;
id | is_deleted | 标题 |
---|---|---|
1 | 假 | TITLE_1 |
2 | 假 | TITLE_2 |
select * from authors;
select * from books b
join books_authors ba on b.id = ba.id_books
join autors a on a.id = ba.id_authors;
id | is_deleted | 标题 | id_books | id_authors | id | is_deleted | 姓名 |
---|---|---|---|---|---|---|---|
1 | 假 | TITLE_1 | 1 | 1 | 1 | 假 | 未删除 |
2 | 假 | TITLE_2 | 2 | 2 | 2 | 真实 | 已删除! |
JPQL:
public Optional<Book> getBookWithSoftDeletedAuthor(long bookId) {
List<Book> myBooks = em.createquery(
"select b from " +
"Book b " +
"left join fetch b.authors a " +
"where b.id = :bookId",Book.class)
.setParameter("bookId",bookId)
.getResultList();
return myBooks.size() > 0 ? Optional.of(myBooks.get(0)) : Optional.empty();
}
持久性.xml:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="WildflyUnit">
<description> Persistence unit for Wildfly </description>
<jta-data-source>java:jboss/datasources/WildflyDataSource</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Postgresql95Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.generate_statistics" value="true" />
</properties>
</persistence-unit>
</persistence>
来自 Wildfly 的 standalone.xml 的数据源:
<datasource jndi-name="java:jboss/datasources/WildflyDataSource" pool-name="WildflyDataSource" enabled="true" use-java-context="true" statistics-enabled="true">
<connection-url>jdbc:postgresql://localhost:5432/TestDB</connection-url>
<driver>postgresql</driver>
<security>
<user-name>wildfly_user</user-name>
<password>********</password>
</security>
</datasource>
select
book0_.id as id1_1_0_,author2_.id as id1_0_1_,book0_.is_deleted as is_delet2_1_0_,book0_.title as title3_1_0_,author2_.is_deleted as is_delet2_0_1_,author2_.name as name3_0_1_,authors1_.id_books as id_books1_2_0__,authors1_.id_authors as id_autho2_2_0__ -- this column is not null even if the author is soft-deleted
from
books book0_
left outer join
books_authors authors1_
on book0_.id=authors1_.id_books
left outer join
authors author2_
on authors1_.id_authors=author2_.id
and (
author2_.is_deleted = false
)
where
(
book0_.is_deleted = false
)
and book0_.id=2
select
book0_.id as id1_1_0_,book0_.id as id_books1_2_0__,author2_.id as id_autho2_2_0__
from
books book0_
left outer join
books_authors authors1_
on book0_.id=authors1_.id_books
left outer join
authors author2_
on authors1_.id_authors=author2_.id
and (
author2_.is_deleted = false
)
where
(
book0_.is_deleted = false
)
and book0_.id=2
id_autho2_2_0__ 列应该来自author2_(authors 表),而不是authors1_(books_authors 表)。由于authors1_.id_authors 列的值不为空,hibernate 尝试从authors 表中获取软删除的实体。
我使用 Hibernate 5.4.27.Final
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。