我正在从Sping Boot 3.1.0迁移到3.1.1,只是一个简单的补丁版本升级。
但是它错误地开始在表上使用JOIN而不是定义的LEFT JOIN。这意味着我得到的结果更少,因为外键是可选的。
回购:
@Query("""
SELECT ak FROM ApiKey ak
LEFT JOIN ak.role r
WHERE ak.projectId = :projectId
""")
Page<ApiKey> find(@Param("projectId") UUID projectId, Pageable pageable);
我们在role
上留下JOIN的原因是因为pageable可以包含role.name
上的排序
但是,现在生成了以下查询:
select a1_0.id,a1_0.created_date,a1_0.db_version,a1_0.expiry_date,a1_0.last_used,a1_0.name,a1_0.project_id,a1_0.public_part,a1_0.role_id,a1_0.secret_key_hash,a1_0.updated_date from api_key a1_0 join role r2_0 on r2_0.id=a1_0.role_id where a1_0.project_id=? order by r2_0.name offset ? rows fetch first ? rows only
它有一个规则的连接,这显然是错误的。除了重写SQL,我还能做什么?
2条答案
按热度按时间xzv2uavs1#
从票证开始的随访:
这实际上不是Hibernate,而是Spring Data,它显然会自动删除
left join
,因为它看不到它的用途,因为sort参数与left join
中的别名不一样。然后,它会自动添加一个常规的join
,以便能够在实际的role.name
排序上进行排序。我猜它是通过在ApiKey中找到role
作为字段名来实现的。我认为一个bug是它没有使用
left join
而是使用join
,因为现在数据由于排序而自动受到限制。这也是一个很大的变化,使在一个小补丁发布。但这里最简单的解决方案是将别名命名为与实体中的字段相同的名称。特别是如果你的页面是由客户端构造的(就像我们的例子),他们不想使用别名缩写作为他们的排序参数。fivyi3re2#
如果Role表是seprate表,那么你应该尝试这样做。
如果你想在同一个表上应用leftjoin,那么试试这个