【问题标题】:JPA/Hibernate maximum number of joins?JPA/Hibernate 最大连接数?
【发布时间】:2009-01-21 22:22:43
【问题描述】:

JPA/Hibernate 查询中允许的连接数是否有限制?

由于 Hibernate doesn't automatically join,我必须在我的 JPA/Hibernate 查询中明确指定连接。例如,人有地址,地址有状态。以下查询检索地址和状态已满载的人员:

select p, a, s from person p left join p.address a left join a.state s where ...

随着我不断添加连接,我最终(在 12-13 个左连接之后)达到了 Hibernate 生成无效 SQL 的限制:

Caused by: java.sql.SQLException: Column 'something69_2_' not found. 

我确实为我的数据库实现 MySQL 设置了 Hibernate 的方言:

<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>

Hibernate 在单个查询中可以处理的连接数是否有限制?

编辑1:日志文件中有以下内容:

could not read column value from result set: something69_2_; Column 'something69_2_' not found.

但是,something69_2_ 不会出现在 SQL 查询中。这就像 Hibernate 生成了一个 SQL 查询并期望 something69_2_ 出现在结果中,但事实并非如此。

编辑 2: 类似问题记录为 unfixed Hibernate bug HHH-3035

编辑 3:这是一个记录在案的 Hibernate bug HHH-3636,它已被修复,但尚未包含在任何版本中。

编辑 4:我构建了 hibernate-core 3.3.2-SNAPSHOT,其中包含错误修复 HHH-3636,但它没有解决这个问题。

编辑 5: 错误行为似乎是由 ManyToMany 或 OneToMany 关系上的多个 LEFT JOIN FETCH 触发的。一个会起作用,两个或三个会导致错误。

编辑 6:这是堆栈跟踪:

javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute query
        at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:629)
        at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:73)
Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
        at org.hibernate.loader.Loader.doList(Loader.java:2214)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2095)
        at org.hibernate.loader.Loader.list(Loader.java:2090)
        at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:388)
        at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
        at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
        at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
        at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
        at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:64)
        ... 69 more
Caused by: java.sql.SQLException: Column 'something69_2_' not found.
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
        at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1136)
        at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2777)
        at org.hibernate.type.IntegerType.get(IntegerType.java:28)
        at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:113)
        at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:102)
        at org.hibernate.loader.Loader.getKeyFromResultSet(Loader.java:1088)
        at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:553)
        at org.hibernate.loader.Loader.doQuery(Loader.java:689)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
        at org.hibernate.loader.Loader.doList(Loader.java:2211)
        ... 77 more

编辑 7:所有这些连接的原因是为了避免 Hibernate 进行 n+1 查询,请参阅Hibernate FAQ on How can I avoid n+1 SQL SELECT queries when running a Hibernate query?

【问题讨论】:

  • 只是好奇,JPA 查询中的 where 子句有多复杂?
  • where 子句无关紧要。我试过 1) 没有 where 子句,2) 简单的 where 子句 (WHERE id=1)。
  • 那为什么不使用 subselect fetch 而不是 join 呢?

标签: java hibernate jpa join


【解决方案1】:

问题是你为什么要首先尝试进行如此复杂的查询?

您是否考虑过不同的方法? improving performance 上的文档提出了一些建议。

【讨论】:

【解决方案2】:

我曾经使用 Hibernate 达到 MySQL 5.0 61 表的限制:

ERROR 1116 (HY000): 表太多; MySQL 在一个连接中只能使用 61 个表

【讨论】:

    【解决方案3】:

    Hibernate 代码中没有限制连接数的内容。这可能是方言中的错误,也可能是数据库引擎的限制。但是我的钱花在了一个与加入数量无关的错误上!您是否尝试过在交互式查询会话中直接运行 SQL?

    【讨论】:

    • SQL 查询运行良好。问题是 Hibernate 试图读取一个不存在的结果字段。
    【解决方案4】:

    您是否尝试过使用实际使用的 jdbc 驱动程序来执行?可能是 jdbc 驱动的问题。

    虽然从列的名称来看,它正在寻找,我猜有一些名称的修剪/构造出错了。绝对看起来更像是一个错误而不是预期的限制。

    【讨论】:

      【解决方案5】:

      您是否正在为您的内部联接的所有 起别名?并使用这些别名?当您尝试在 SELECT 子句中使用隐式别名来执行此类操作时,我已经看到 Hibernate 的一些非常奇怪的行为(极其简化的示例):

      select p.address.state from person p
      

      但是,如果您明确声明所有别名,它就可以正常工作。像这样:

      select s from person p join p.address a join a.state s
      

      ...甚至这个:

      select s from person p join p.address.state s
      

      【讨论】:

        猜你喜欢
        • 2017-08-25
        • 1970-01-01
        • 2017-06-21
        • 2011-03-29
        • 2016-10-24
        • 2015-03-09
        • 2012-12-19
        • 2015-02-09
        • 1970-01-01
        相关资源
        最近更新 更多