【发布时间】:2022-10-24 03:38:30
【问题描述】:
我已经通过 JPA 映射了以下实体:
@Entity(name = "Parent")
@Table(name = "parent")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type")
public abstract class Parent {
@Id
@GenericGenerator(name = "CustomUUIDGenerator", strategy = "package.CustomUUIDGenerator")
@GeneratedValue(generator = "CustomUUIDGenerator", strategy = GenerationType.AUTO)
private UUID id;
@ManyToMany
@Fetch(FetchMode.JOIN)
@JoinTable(name = "parent_country", joinColumns = @JoinColumn(name = "parent_id"),
inverseJoinColumns = @JoinColumn(name = "country_id"))
private Set<Country> countries;
}
@Entity(name = "ChildA")
@Table(name = "child_a")
@DiscriminatorValue(value = "CHILD_A")
public class ChildA extends Parent {
private String description;
}
这反映到以下 Postgres 的表模式:
表 PARENT 列:ID、TYPE
表 COUNTRY 列:ID、CODE、LANGUAGE
表 PARENT_COUNTRY 列:PARENT_ID、COUNTRY_ID
表 CHILD_A 列:ID、DESCRIPTION
基于此,我正在尝试使用EntityGraph 创建一个CriteriaQuery 来控制动态关联实体的加载。
以下代码显示了给定查询的方式:
EntityGraph<ChildA> entityGraph = entityManager.createEntityGraph(ChildA.class);
entityGraph.addAttributeNodes(Parent_.COUNTRIES);
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<ChildA> criteriaQuery = criteriaBuilder.createQuery(ChildA.class);
Root<ChildA> root = criteriaQuery.from(ChildA.class);
List<Predicate> predicates = new ArrayList<>();
final Join<ChildA, Country> join = root.join(ChildA_.COUNTRIES, JoinType.LEFT);
predicates.add(criteriaBuilder.equal(join.get(Country_.CODE), "USA"));
criteriaQuery.where(predicates.toArray(Predicate[]::new));
TypedQuery<ChildA> finalQuery = entityManager
.createQuery(criteriaQuery)
.setHint(EntityGraphPersistence.LOAD_GRAPH, entityGraph);
List result = finalQuery.getResultList();
问题是,当我运行上面的查询时,我会在控制台上打印以下 SQL:
select
* -- All hibernate fields from all entities
from
child_a ca
inner join
parent pa
on ca.id=pa.id
left outer join
parent_country pc
on pc.parent_id = ca.id
left outer join
country co
on pc.country_id = co.id
left outer join
parent_country pc_2
on pc2.parent_id = ca.id
left outer join
country co2
on pc2.country_id = co2.id
where
(
co.code=?
)
上面查询的问题是 PARENT_COUNTRY 和 COUNTRY 的双重联接。在这个查询中,我根据国家代码(等于美国)过滤结果,所以我不想从其他国家(不同于美国)的数据库中返回。但是,由于第二次左连接到国家,父级再次与国家/地区相关,并且对与co.code=? 的第一个关系进行的过滤器被忽略。
有谁知道如何防止这个用例中的双重加入?
【问题讨论】:
标签: java hibernate jpa hibernate-criteria entitygraph