【问题标题】:Inefficient JPA query using compound Where clause使用复合 Where 子句的低效 JPA 查询
【发布时间】:2021-01-02 01:34:42
【问题描述】:

我有一个具有如下一对多关系的表

城市->学校->老师->孩子

我从城市检索孩子的 JPQL 如下

@Query("Select c  from Children c where c.teacher.school.city=:city")
Set<Children> findChildrenFromCity(@Param("city") City city);

reference herereference here 关于 Where 子句 这么说

“复合路径表达式使 where 子句非常强大。”

但是,在观察日志后,我意识到上面的查询正在做一些奇怪的事情,比如

  1. 生成多个 Select 而不是一个 Select

  2. 在日志中可以看到一些交叉连接

我试图了解我是否正确定义了我的查询,如果复合 Where 确实如此强大,为什么我的查询效率如此低。

【问题讨论】:

  • 实际的 SQL 是什么样子的?请将其添加到您的问题中。
  • 您有Bidirectioanl 映射?
  • 是的,双向映射,一侧有适当的 mappedBy。
  • 看这么少的代码很不清楚。多重选择也可能是延迟提取或放置不当的 EAGER 提取的结果。请发布记录的查询(或子集)和实体代码;只需带有映射注释的属性就足够了。

标签: java spring jpa spring-data-jpa


【解决方案1】:

您可以使用以下方法:

Set<Children> findAllByTeacherSchoolCity(String city);

假设您的班级 Children 有字段 Teacher teacherTeacherSchool schoolSchoolString city

如有差异,请在 cmets 中询问。

【讨论】:

  • 这是一个不错的建议。但是,我有很多用例,我想使用 JPQL,并试图通过我上面的问题来理解行为。尤其是为什么会发生交叉连接和发生多选。
  • 我不认为你真的需要 JPQL 查询。从接口方法签名解析查询的引擎非常强大。如果您希望查询使用连接,请使用适当的 @Fetch 注释属性
【解决方案2】:

试试这个

@Query("Select c from City city join city.schools s join s.teachers t join t.childrens c where city = :city")
Set<Children> findChildrenFromCity(@Param("city") City city);

此查询正在运行一个 Select 查询以获取 Children 实体。检查下面提到的日志。

休眠:选择 childrens3_.id 作为 id1_0_, childrens3_.date_created AS date_cre2_0_, childrens3_.date_updated AS date_upd3_0_, childrens3_.NAME AS name4_0_, childrens3_.teacher_id AS teacher_5_0_ FROM city city0_ INNER JOIN 学校学校1_ ON city0_.id =学校1_.city_id INNER JOIN 教师教师2_ ON 学校 1_.id = 教师 2_.school_id INNER JOIN 儿童 childrens3_ ON Teachers2_.id = childrens3_.teacher_id WHERE city0_.id = ?

现在你有一个n+1 问题。要解决此类问题,您可以使用 join fetch 而不是简单的连接。

【讨论】:

  • 此查询给出的选择数与我的查询给出的完全相同。澄清一下,我的查询确实有效。最终发生的选择数量非常低效。
  • @CaptainHackSparrow 检查我更新的答案。该查询正在运行一个选择语句来获取children。您的查询一定有 n+1/lazy fetch 问题。
【解决方案3】:

如果你想使用查询注解试试这个方法

@Query("Select c  from Children c join fetch c.teacher t join fetch t.school s join fetch s.city ct where ct.id = :id")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-11
    • 1970-01-01
    • 2011-07-05
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-15
    相关资源
    最近更新 更多