JPA - 为什么投 Fetch 加入
JPA - Why cast Fetch to Join
为什么有时需要施法?
Join<X, Y> a = (Join) Fetch<X, Y> ...
例如:
Root<Person> personRoot = criteriaQuery.from(Person.class);
@SuppressWarnings("unchecked")
Join<Person, Loan> loanJoin = (Join) personRoot.fetch("loan", JoinType.INNER);
loanJoin.fetch("borrower", JoinType.LEFT);
没有做的原因是什么:
Fetch<Person, Loan> fetchJoin = personRoot.fetch("loan", JoinType.INNER);
fetchJoin.fetch("borrower", JoinType.LEFT);
当我想获得两者的好处时,我不得不将 Fetch
转换为 Join
。
Fetch
允许在注解不起作用时预先加载请参阅
Join
允许在连接关系 的属性上添加 restriction/order
例如,假设您想要将所有 Employee
连同有关其部门和祖国的信息作为具有两个内部联接的单个 select 查询来获取。这可以通过为 department
和 homeCountry
添加一个 root.fetch(...)
来实现。如果您还希望根据各自所在国家/地区的人口对员工进行排序(请假设您愿意),您将需要 Join
Root<Employee> root = query.from(Employee.class);
root.fetch("department"); // <- for an eager join
Join<Employee,Country> joinCountry = (Join) root.fetch("homeCountry"); // <- for an eager join & orderBy
query.select(root).orderBy(builder.asc(joinCountry.get("population")));
Query<Employee> q = sessionFactory.getCurrentSession().createQuery(query);
List<Employee> employees = q.getResultList();
以上代码向 db
触发一个 select *
select
employee0_.emp_id as emp_id1_0_0_,
department1_.department_id as depart1_2_1_,
country2_.country_id as countr1_3_2_,
employee0_.salary as salary2_0_0_,
department1_.name as name3_0_0,
country2_.continent as continent4_0_0
from
employee employee0_
inner join
department department1_
on employee0_.department_id=department1_.department_id
inner join
country country2_
on employee0_.country_id=country2_.country_id
order by
country2_.population asc
确定的答案在这里:How to properly express JPQL "join fetch" with "where" clause as JPA 2 CriteriaQuery?
基本上,JPA 提供 @OneToMany
,需要将 所有相关实体 提取到 Collection
。如果您允许别名为 Fetch
(如 javax.persistence.criteria.Path.get(String)
),则可以添加 where
或 on
表达式来限制 Collection
破坏 JPA Java 模型假设。
@*ToOne
联接没有问题,因此一些 JPA 实现允许将 Fetch
强制转换为 Join
假设您了解自己在做什么))
其他阅读:
- Using the JPA Criteria API, can you do a fetch join that results in only one join?
- Navigation method/s in criteria fetch joins in JPA 2.1
为什么有时需要施法?
Join<X, Y> a = (Join) Fetch<X, Y> ...
例如:
Root<Person> personRoot = criteriaQuery.from(Person.class);
@SuppressWarnings("unchecked")
Join<Person, Loan> loanJoin = (Join) personRoot.fetch("loan", JoinType.INNER);
loanJoin.fetch("borrower", JoinType.LEFT);
没有做的原因是什么:
Fetch<Person, Loan> fetchJoin = personRoot.fetch("loan", JoinType.INNER);
fetchJoin.fetch("borrower", JoinType.LEFT);
当我想获得两者的好处时,我不得不将 Fetch
转换为 Join
。
Fetch
允许在注解不起作用时预先加载请参阅Join
允许在连接关系 的属性上添加 restriction/order
例如,假设您想要将所有 Employee
连同有关其部门和祖国的信息作为具有两个内部联接的单个 select 查询来获取。这可以通过为 department
和 homeCountry
添加一个 root.fetch(...)
来实现。如果您还希望根据各自所在国家/地区的人口对员工进行排序(请假设您愿意),您将需要 Join
Root<Employee> root = query.from(Employee.class);
root.fetch("department"); // <- for an eager join
Join<Employee,Country> joinCountry = (Join) root.fetch("homeCountry"); // <- for an eager join & orderBy
query.select(root).orderBy(builder.asc(joinCountry.get("population")));
Query<Employee> q = sessionFactory.getCurrentSession().createQuery(query);
List<Employee> employees = q.getResultList();
以上代码向 db
触发一个select *
select
employee0_.emp_id as emp_id1_0_0_,
department1_.department_id as depart1_2_1_,
country2_.country_id as countr1_3_2_,
employee0_.salary as salary2_0_0_,
department1_.name as name3_0_0,
country2_.continent as continent4_0_0
from
employee employee0_
inner join
department department1_
on employee0_.department_id=department1_.department_id
inner join
country country2_
on employee0_.country_id=country2_.country_id
order by
country2_.population asc
确定的答案在这里:How to properly express JPQL "join fetch" with "where" clause as JPA 2 CriteriaQuery?
基本上,JPA 提供 @OneToMany
,需要将 所有相关实体 提取到 Collection
。如果您允许别名为 Fetch
(如 javax.persistence.criteria.Path.get(String)
),则可以添加 where
或 on
表达式来限制 Collection
破坏 JPA Java 模型假设。
@*ToOne
联接没有问题,因此一些 JPA 实现允许将 Fetch
强制转换为 Join
假设您了解自己在做什么))
其他阅读:
- Using the JPA Criteria API, can you do a fetch join that results in only one join?
- Navigation method/s in criteria fetch joins in JPA 2.1