JPA/Hibernate クエリで許可される結合数に制限はありますか?
Hibernateは自動的に 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.
Hibernate の方言をデータベース実装の MySQL に設定しています。
<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:未修正の Hibernate バグ HHH-3035として文書化された同様の問題
編集 3:これは文書化されたHibernate バグ HHH-3636であり、修正されていますが、まだどのリリースにも含まれていません。
編集 4:バグ修正 HHH-3636 を含む hibernate-core 3.3.2-SNAPSHOT をビルドしましたが、この問題は解決されませんでした。
編集 5:バグの動作はLEFT JOIN FETCH
、ManyToMany または OneToMany の複数の関係によって引き起こされるようです。1 つが機能し、2 つまたは 3 つがバグになります。
編集 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 クエリを実行するときに n+1 SQL SELECT クエリを回避するにはどうすればよいですか?