3

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 クエリを回避するにはどうすればよいですか?

4

5 に答える 5

2

Hibernate で MySQL 5.0 の 61 テーブル制限に達したことがあります。

エラー 1116 (HY000): テーブルが多すぎます。MySQL は結合で 61 個のテーブルしか使用できません
于 2009-03-13T22:14:01.550 に答える
2

問題は、そもそもなぜこのような複雑なクエリを作成しようとしているのかということです。

さまざまなアプローチを検討しましたか?パフォーマンスの改善に関するドキュメントには、いくつかの提案があります。

于 2009-03-15T22:04:12.533 に答える
1

結合の数を制限する Hibernate コード内には何もありません。これは方言のバグか、データベース エンジンの制限である可能性があります。しかし、私のお金は、参加数とは関係のないバグにあります! 対話型クエリ セッションで SQL を直接実行してみましたか?

于 2009-01-21T22:26:57.900 に答える
0

すべての内部結合をエイリアシングしていますか?そして、それらのエイリアスを使用しますか?句で暗黙のエイリアシングを使用して次のようなことを実行しようとすると、Hibernateで非常に奇妙な動作が見られますSELECT(非常に単純化された例)。

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
于 2012-12-05T15:03:49.433 に答える
0

使用中の実際の jdbc ドライバーで実行しようとしましたか? jdbc ドライバーの問題である可能性があります。

列の名前から判断すると、探していますが、名前のトリミング/構成がうまくいかないことがあると思います。間違いなく、意図した制限よりもバグのように見えます。

于 2009-03-15T16:36:55.270 に答える