異常,如果我用一個返回Stream
Spring的數據存儲庫的方法,我總是得到以下異常:春數據JPA流查詢方法引起有關事務
org.springframework.dao.InvalidDataAccessApiUsageException: You're trying to execute a streaming query method without a surrounding transaction that keeps the connection open so that the Stream can actually be consumed. Make sure the code consuming the stream uses @Transactional or any other way of declaring a (read-only) transaction.
org.springframework.data.jpa.repository.query.JpaQueryExecution$StreamExecution.doExecute(JpaQueryExecution.java:338)
org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:85)
org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:116)
org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106)
org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:483)
org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
com.sun.proxy.$Proxy201.findByPodcast(Unknown Source)
<my controller class>$$Lambda$118/2013513791.apply(Unknown Source)
有問題的代碼真的應該到然而,在交易中執行。我有:
- 使用的
OpenSessionManagerInViewFilter
- 啓用聲明式事務管理(
@EnableTransactionManagement
在我的根上下文的配置),並註明控制器類和與@Transactional
請求方法我已經還嘗試將代碼包裝在TransactionTemplate
中,並將結果收集到List
中以避免事務超出範圍,但這仍然無效。控制方法:
@RequestMapping ("/pod/{id}")
@Transactional
public Stream<RSSPodcastItem> podItems (@PathVariable("id") UUID id)
{
return pods.get (id).map (items::findByPodcast).orElseThrow (() -> new RuntimeException ("failed"));
}
@RequestMapping ("/podlist/{id}")
@Transactional
public List<RSSPodcastItem> podItemsList (@PathVariable("id") UUID id)
{
return tt.execute (ts ->
pods.get (id).map (items::findByPodcast).orElseThrow (() -> new RuntimeException ("failed"))
.collect (Collectors.toList()));
}
上下文根配置類:
@Configuration
@ComponentScan (... my package names ...)
@EnableTransactionManagement
@EnableJpaRepositories(... package with repositories ...)
public class SharedConfig
{
@Bean
public DataSource dataSource()
{
// .... snipped
}
@Bean
EntityManagerFactory entityManagerFactory()
{
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource (dataSource());
entityManagerFactoryBean.setJpaVendorAdapter (new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan (... package with entities ...);
entityManagerFactoryBean.setJpaPropertyMap (hibernateProperties());
entityManagerFactoryBean.afterPropertiesSet();
return entityManagerFactoryBean.getObject();
}
@Bean
JpaTransactionManager transactionManager()
{
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory (entityManagerFactory());
return transactionManager;
}
@Bean
TransactionTemplate transactionTemplate (JpaTransactionManager tm)
{
return new TransactionTemplate (tm);
}
@Bean
Map<String, ?> hibernateProperties()
{
Map<String, Object> m = new HashMap<>();
m.put ("hibernate.dialect", MySQL5Dialect.class);
m.put ("hibernate.dialect.storage_engine", "innodb");
boolean devSystem = isDevSystem();
m.put ("hibernate.hbm2ddl.auto", devSystem ? "update" : "create-only"); // will need to handle updates by hand on live system, but creation is OK.
m.put ("hibernate.show_sql", "" + devSystem);
m.put ("hibernate.cache.use_second_level_cache", "" + !devSystem);
return m;
}
任何建議是怎麼回事錯在這裏?
我的回答對你有幫助嗎?.. – Cepr0