Hibernate 在第一次 fetch-joining 然后 simple-joining 时不生成 JOIN
Posted
技术标签:
【中文标题】Hibernate 在第一次 fetch-joining 然后 simple-joining 时不生成 JOIN【英文标题】:JOIN not generated by Hibernate when first fetch-joining then simple-joining 【发布时间】:2018-09-16 17:29:20 【问题描述】:给定以下实体:
@Entity
public class User
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "user", fetch = LAZY)
private Set<UserRole> userRoles = new HashSet<>();
@Entity
public class UserRole
@Id
private Long id;
private String name;
@ManyToOne(fetch = LAZY)
private User user;
@ManyToMany(fetch = LAZY)
private Set<Article> articles = new HashSet<>();
@Entity
public class Article
@Id
private Long id;
private String name;
@ManyToMany(mappedBy = "articles", fetch = LAZY)
private Set<UserRole> userRoles = new HashSet<>();
我正在构建以下查询:
From<?, ?> root = query.from(User.class);
From<?, ?> joinedUserRoles = (From<?, ?>) root.fetch("userRoles", JoinType.INNER);
From<?, ?> joinedArticles = joinedUserRoles.join("articles", JoinType.INNER);
query.where(joinedArticles.in(someArticles));
这个想法是在简单加入UserRole#articles
的同时获取加入User#userRoles
。问题是生成的查询无效:
select
user0_.id as id1_6_0_,
userroles1_.id as id1_7_1_,
user0_.name as name5_6_0_,
userroles1_.role as role2_7_1_,
userroles1_.user_id as User_i3_7_1_,
userroles1_.user_id as User_i3_7_0__,
userroles1_.id as id1_7_0__
from
User user0_
inner join
UserRole userroles1_
on user0_.id=userroles1_.user_id
where
generatedAlias2 in (
?
)
抛出的错误:
SQLSyntaxErrorException: Unknown column 'generatedAlias2' in 'where clause'
确实,JPA/Hibernate 出于某种原因没有生成简单连接 UserRole#articles
。
知道发生了什么吗?
我使用的是 Hibernate 5.2.16。
【问题讨论】:
不清楚你的目标是什么。什么是用户角色?是不是类似于“OriginalPoster”和“Responder”?如果是这样,您为什么在那里有文章列表?为什么在 User 类中没有文章列表?此外,为什么要在文章中列出用户角色?可以有多少个 UserRole?如前所述,如果只有两个,那么在此处列出该列表是没有意义的。你真的需要明确你的目标。 @KarlNicholas 感谢您的评论。实体已经过彻底设计,所有这些关系都是我们模型所需的。我真的不知道我可以提供什么额外的细节。基本上,问题是:如何在获取加入后进行简单加入。我不确定这里还需要什么。 对,那么UserRole的作用是什么? 【参考方案1】:根据Batch fetching - optimizing object graph loading:
JPQL 不允许 join fetch 的别名,因此如果您还想查询关系,则必须加入两次。
in this answer 给出了禁止这样做的示例。
您的转换允许构造条件对象,但提供者似乎无法正确理解它并且无法解析 articles
别名。
将fetch()
替换为join()
在加载惰性关系方面可能并不理想,但应该构造一个有效的查询。
【讨论】:
有趣的链接,谢谢!我不知道 fetch-joins 不能使用别名。我明天再试一次,我会回来找你的。【参考方案2】:又看了一遍:这有什么问题?似乎有效。
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> user = cq.from(User.class);
Join<User, UserRole> userRoles = user.join("userRoles", JoinType.INNER);
Join<UserRole, Article> articles = userRoles.join("articles", JoinType.INNER);
cq.where(articles.in(Arrays.asList(new Long[]1L)));
【讨论】:
以上是关于Hibernate 在第一次 fetch-joining 然后 simple-joining 时不生成 JOIN的主要内容,如果未能解决你的问题,请参考以下文章
使用hibernate 5如何在第一次执行时创建一个带有ROW的表?