2016-10-24 3 views
6

のために働いていない私は、JPA + Hibernateの構成やクエリキャッシュとEH-キャッシュを使用して、第2レベルのキャッシュを持っています。休止状態Ehcacheのは、私は、エラー</p> <pre><code>aliases expected length is 1; actual length is 4 at org.hibernate.transform.CacheableResultTransformer.transformTuple </code></pre> <p>を取得していますSQLネイティブクエリキャッシュ

構成: のPostgreSQL 9.6 + JPA 2.1 + Hibernateは5.2.3.Final

私はSqlResultSetMappingとNativeQuery [カスタム結果セットのクラス]を実行しようとしています。キャッシュを無効にすると、すべてうまく動作しています。

しかし、キャッシュを有効にしているときに上記エラーが表示される。キャッシュはNativeQueryを除いて正常に動作しています。

テーブルスキーマ:

PK first second third 

1 A  abc  C  
2 A  abc  C  
3 A  xyz  D  
4 B  abc  C  
5 B  xyz  C  
6 B  abc  D  
7 A  xyz  C  
8 A  abc  D  

SQLネイティブQUERY:

SELECT t.first,t.second, 
    COUNT(t.second) total, 
    COALESCE(t1.ccount, 0) ccount, 
    COALESCE(t2.dcount, 0) dcount 
FROM test t 
LEFT JOIN (SELECT 
    COUNT(third) AS ccount, FIRST, SECOND 
    FROM test 
    WHERE third = 'C' 
    GROUP BY SECOND,FIRST) t1 
ON (t1.first = t.first AND t1.SECOND = t.SECOND) 
LEFT JOIN (SELECT 
    COUNT(third) AS dcount, FIRST, SECOND 
    FROM test 
    WHERE third = 'D' 
    GROUP BY SECOND,FIRST) t2 
ON (t2.first = t.first AND t2.SECOND = t.SECOND) 
GROUP BY t.SECOND, t.first; 

SqlResultSetMapping

@SqlResultSetMapping(name = "RESULT_SET_NAME", classes = { 
     @ConstructorResult(targetClass = TestResult.class, 
      columns = { @ColumnResult(name = "first", type = String.class), 
         @ColumnResult(name = "second", type = String.class), 
         @ColumnResult(name = "total", type = String.class), 
         @ColumnResult(name = "ccount", type = String.class), 
         @ColumnResult(name = "dcount", type = String.class) }) }) 

query = getEntityManager().createNativeQuery(nativeQuery, "RESULT_SET_NAME"); 
query.setHint("org.hibernate.cacheable", true); 
result = query.getResultList(); 

期待される結果セット

first second total ccount dcount 
------ ------ ------ ------ -------- 
A  abc   3  2   1 
B  abc   2  1   1 
A  xyz   2  1   1 
B  xyz   1  1   0 

スタックトレース

aliases expected length is 1; actual length is 4 
java.lang.IllegalStateException: aliases expected length is 1; actual length is 4 
    at org.hibernate.transform.CacheableResultTransformer.transformTuple(CacheableResultTransformer.java:155) 
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:770) 
    at org.hibernate.loader.Loader.processResultSet(Loader.java:985) 
    at org.hibernate.loader.Loader.doQuery(Loader.java:943) 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349) 
    at org.hibernate.loader.Loader.doList(Loader.java:2615) 
    at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2460) 
    at org.hibernate.loader.Loader.list(Loader.java:2422) 
    at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335) 
    at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2129) 
    at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:981) 
    at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:147) 
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1398) 
    at org.hibernate.Query.getResultList(Query.java:417) 
+1

WHATクエリHibernateマッピングXMLで

SQLQuery sqlQuery = session.createSQLQuery("ALTER SESSION SET NLS_COMP = 'BINARY'"); sqlQuery.addSynchronizedQuerySpace(""); /* * Only the empty query space "" will be invalidated. * So no cache will be invalidated, because no table with an empty name exists */ int updatedEntities = sqlQuery.executeUpdate(); 

?何のスタックトレース?どのような構成ですか?どのAPIが呼び出されますか? –

+0

@BillyFrost、私はすべての詳細を追加しました。編集した質問をチェックしてください。 – Kunal

+0

与えられた例を使用するようにConstructorResultNativeQueryTestを修正しましたが、エラーなしで動作します。 http://pastebin.com/Cj5YntaCあなたのJAVA_HOMEをJDK8パスに設定し、 './gradlew hibernate-core:test --tests * ConstructorResultNativeQueryTest -Pdb = pgsql'を実行します(データベース' hibernate_orm_test 'と同じ名前とパスワードで完全なアクセス権を持っているユーザー)。私はあなたのエラーを複製することはできません。 – coladict

答えて

1

あなたの場合、EHCacheはJPQLクエリでのみ使用できます。つまり、サブ選択、共用体または同様のネイティブSQL構造を使用しないようにクエリを書き直す必要があります。

0

HibernateはネイティブSQLクエリを実行しているときに何をしているのか分からないため、どのキャッシュを無効化する必要があるかを知ることができません。休止状態が影響を受けるキャッシュを知らない限り、データの一貫性を保証するためにすべてのデータが無効であると仮定する必要があります。これは、休止状態がすべてのキャッシュを無効にすることを意味します。

Fortunatlyでは、hibernate APIを使用して、クエリの影響を受けるエンティティまたはクエリ空間を指定できます。 どのテーブルがクエリの影響を受けるかをhibernateに伝え、hibernateはそのデータに基づいたキャッシュのみを無効にします。エンティティ名

sqlQuery.addSynchronizedEntityClass(Person.class); 
sqlQuery.addSynchronizedEntityName("com.link_intersystems.xhibernate.testclasses.Person"); 
sqlQuery.addSynchronizedQuerySpace("SOME_TABLE"); 

SQLQuery sqlQuery = session.createSQLQuery("UPDATE CUSTOMER SET ... WHERE ..."); 
sqlQuery.addSynchronizedEntityClass(Person.class); 
int updatedEntities = sqlQuery.executeUpdate(); 

時々、あなたは、任意のデータを変更しないネイティブクエリを実行します。休止状態が第2レベルのキャッシュを無効にしないようにするには、空の照会スペースの同期を追加することができます。

<sql-query name="setNLSCompBinary"> 
<!-- an empty synchronize tag prevents hibernate from invalidating second level caches --> 
<synchronize table="" /> 
    ALTER SESSION SET NLS_COMP = 'BINARY' 
</sql-query> 

impact-of-native-sql-queries-on-hibernates-second-level-cache

関連する問題