2017-04-12 11 views
1

春天數據在Spring數據,我怎麼會提示休眠影響表本地更新SQL

@Modifying 
@Query(value = "update user set name='abc'", nativeQuery = true) 
int changeThemAll(); 

由於Modifying,這個查詢將無效所有緩存,因爲Hibernate無法找出受影響的實體。 在org.hibernate.action.internal.BulkOperationCleanupAction#affectedEntity,如果沒有表空間,會考慮表受到影響。

這成爲問題

  1. 如果該區域是隻讀的,則hazelcast休眠二級緩存FPGA實現會拋出異常。
  2. 當在高速緩存中的條目很多,無效所有的表會影響系統

另外,我發現這個article描述休眠XML配置的解決方案。

我能想到的解決方法是刪除@Modifying和手動無效緩存或使用JdbcTemplate運行本機SQL和手動使緩存失效。

完整堆棧跟蹤

at com.hazelcast.hibernate.access.ReadOnlyAccessDelegate.lockRegion(ReadOnlyAccessDelegate.java:72) 
at com.hazelcast.hibernate.region.EntityRegionAccessStrategyAdapter.lockRegion(EntityRegionAccessStrategyAdapter.java:99) 
at org.hibernate.action.internal.BulkOperationCleanupAction$EntityCleanup.<init>(BulkOperationCleanupAction.java:209) 
at org.hibernate.action.internal.BulkOperationCleanupAction$EntityCleanup.<init>(BulkOperationCleanupAction.java:203) 
at org.hibernate.action.internal.BulkOperationCleanupAction.<init>(BulkOperationCleanupAction.java:110) 
at org.hibernate.engine.query.spi.NativeSQLQueryPlan.coordinateSharedCacheCleanup(NativeSQLQueryPlan.java:152) 
at org.hibernate.engine.query.spi.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:176) 
at org.hibernate.internal.SessionImpl.executeNativeUpdate(SessionImpl.java:1373) 
at org.hibernate.internal.SQLQueryImpl.executeUpdate(SQLQueryImpl.java:373) 
at org.hibernate.jpa.internal.QueryImpl.internalExecuteUpdate(QueryImpl.java:405) 
at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:61) 
at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:238) 
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:85) 
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:116) 
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106) 
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:483) 
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 

Hazelcast ReadOnlyAccessDelegate#lockRegion FPGA實現

@Override 
public SoftLock lockRegion() throws CacheException { 
    throw new UnsupportedOperationException("Attempting to lock a read-only cache region: " 
      + getHazelcastRegion().getName()); 
} 

編輯

的問題是我怎麼會提示本機更新SQL休眠受影響的表。

例如

@org.springframework.data.jpa.repository.QueryHints({ 
    @QueryHint(name = QueryHints.HINT_CACHE_REGION, value = "UserEntity"), 
    // Something like this @QueryHint(name = QueryHints.HINT_AFFECTED_ENTITIES, value = "UserEntity"), 
}) 

我可以暗示用於結果的緩存區域,但是如何提示表空間或受影響的實體?

相關方法

  • org.hibernate.loader.custom.CustomQuery#getQuerySpaces
  • org.hibernate.SQLQuery#addSynchronizedQuerySpace
  • org.hibernate.SQLQuery#addSynchronizedEntityName
  • org.hibernate作爲。 SQLQuery#addSynchronizedEntityClass
+0

您描述了一個問題和解決方案。什麼是問題? –

回答

0

看着你的stacktrace,我假設你正在使用read-只有區域緩存策略。

當您使用只讀作爲緩存策略時,您無法使用Hibernate更新該區域中的數據。由於預計不會更新該區域中的數據,因此Hibernate二級緩存提供程序不會爲只讀緩存區域實施lockRegion操作,只有在使緩存區域無效時纔會使用該操作。

我建議在該地區使用不同的緩存策略(可能有read-write),因爲您顯然需要修改該表中的數據。

+0

在只讀緩存中只有很少的實體,我們應該保留這一點,相反,我想告訴休眠只會使受影響的實體無效,而不是全部。實際上,我可以將緩存更改爲rw,但這不是我想要的。 – wener