【问题标题】:Spring-Data JPA: InvalidDataAccessApiUsageException for @TransactionalSpring-Data JPA:@Transactional 的 InvalidDataAccessApiUsageException
【发布时间】:2018-06-27 14:38:56
【问题描述】:

我使用 @EnableTransactionManagement 运行 Spring Boot 应用程序,并希望使用 @Transactional(readOnly = true) 进行一些数据库查询。

但我收到一条令人困惑的错误消息。 我正在使用 Spring、Spring Boot 和 Spring Data JPA。

MySpringBootApplication.java

@SpringBootApplication
@EnableTransactionManagement
@ComponentScan("com.deutscheboerse.regrephub")
@EntityScan(basePackages = "com.deutscheboerse.regrephub")
@EnableJpaRepositories(basePackages = "com.deutscheboerse.regrephub")
@Slf4j
public class MySpringBootApplication
{
   ... Some @Autowired variables ...

   public static void main(String[] args)
   {
      SpringApplication.run(MySpringBootApplication.class, args);
   }

   ... 
}

MySpringBootApplicationConfiguration.java

@Configuration
@EnableEncryptableProperties
@EnableTransactionManagement
@EnableAsync
@Slf4j
public class MySpringBootApplicationConfiguration
{
   ... Some @Autowired variables ...

   @Bean
   @ConfigurationProperties(prefix = "spring.datasource")
   public DataSource dataSource()
   {
      return DataSourceBuilder
            .create(this.dataSourceProperties.getClassLoader())
            .url(this.dataSourceProperties.getUrl())
            .username(this.dataSourceProperties.getUsername())
            .password(this.dataSourceProperties.getPassword())
            .build();
    }

    ...
}

MyBeanDao.java

@Repository
public interface MyBeanDao extends JpaRepository<MyBeanData, Long>
{
    @QueryHints(value = @QueryHint(name = HINT_FETCH_SIZE, value = "" + Integer.MIN_VALUE))
    @Query(value = "SELECT * FROM MY_TABLE", nativeQuery = true)
    @Transactional(readOnly = true)
    Stream<MyBeanData> streamAll();
}

MyBeanService.java

@Service
@Slf4j
public class MyBeanService extends AbstractService
{
    @Autowired
    public MyBeanService(...)
    {
       ...
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public void handleRequest(Object request, Message msg)
    {
       try (Stream<MyBeanData> data = myBeanDao.streamAll())
       {
          ...
       }
       catch (Exception e)
       {
          ...
       }
    }
}

当我运行我的 SpringBootApplication 时,我将收到以下日志消息/错误:

[TransactionInterceptor:474] Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.streamAll]
[TransactionInterceptor:517] Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.streamAll] after exception: 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.
[RuleBasedTransactionAttribute:131] Applying rules to determine whether transaction should rollback on 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.
[RuleBasedTransactionAttribute:148] Winning rollback rule is: null
[RuleBasedTransactionAttribute:153] No relevant rollback rule found: applying default rules

第一个 JPA 打开一个事务并立即关闭它,但有一个异常,我想在没有周围事务的情况下执行流式查询方法。 以前有人有过吗?!

【问题讨论】:

  • 为什么要传播到支持?请试试这个:1)从服务中删除传播元数据(保留默认值)2)从存储库接口中删除@Transactional(不需要)。运行你的代码,看看是否正常
  • 您推荐的更改我收到此错误:[TransactionInterceptor:483] Don't need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.streamAll]: This method isn't transactional.
  • 后跟异常: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.
  • 这没有多大意义..你能从这个特定的调用层次结构中的任何地方删除@Transactional,然后再试一次吗?以下是使用存储库中的 Stream 的 java 8 示例github.com/spring-projects/spring-data-examples/tree/master/jpa/…
  • 我删除了所有带有@Transactional 的注释并得到与上面相同的日志消息/错误。

标签: java spring hibernate spring-data-jpa transactional


【解决方案1】:

MyBeanData.java

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "MY_TABLE_NAME")
@Data
@NoArgsConstructor
public class ValLeiPageData
{
    @Id
    private Long id;

    ...
}

所以是的,对于上面的评论,MyDataBean 是一个实体。

这些是上面cmet中提到的更改后的类:

MyBeanDao.java

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
...

@Repository
public interface MyBeanDao extends JpaRepository<MyBeanData, Long>
{
    // removed @Query annotation
    Stream<MyBeanData> streamAll();
}

MyBeanService.java

import org.springframework.stereotype.Service;

@Service
@Slf4j
public class MyBeanService extends AbstractService
{
    @Autowired
    public MyBeanService(...)
    {
       ...
    }

    @Override
    public void handleRequest(Object request, Message msg)
    {
       try (Stream<MyBeanData> data = myBeanDao.streamAll())
       {
          ...
       }
       catch (Exception e)
       {
          ...
       }
    }
}

当我启动应用程序时,我收到错误: org.springframework.data.mapping.PropertyReferenceException: No property streamAll found for type MyBeanData!

maven依赖有:

  • org.springframework.boot:spring-boot-starter:1.5.6.RELEASE
  • org.springframework.boot:spring-boot-starter-test:1.5.6.RELEASE
  • org.springframework.boot:spring-boot-starter-web:1.5.6.RELEASE
  • org.springframework.boot:spring-boot-starter-data-jpa:1.5.6.RELEASE
    • org.hibernate:hibernate-core:5.0.12.Final
    • org.hibernate:hibernate-entitymanager:5.0.12.Final
    • org.springframework.data:spring-data-jpa:1.11.6.RELEASE
    • ...
  • ...

这可能是依赖问题吗? 我找不到 spring/spring-boot/spring-data 依赖矩阵...

【讨论】:

  • 使用Stream&lt;MyBeanData&gt; readAllByMyColumnNotNull(); 修复了错误消息No property streamAll found for type MyBeanData 但我仍然收到错误消息:[TransactionInterceptor:483] Don't need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.readAllByMyColumnNotNull]: This method isn't transactional. 后跟org.springframework.dao.InvalidDataAccessApiUsageException: You're trying to execute a streaming query method without a surrounding transaction .....
【解决方案2】:

我修好了!

这是弹簧上下文的问题。

当我初始化 MyBeanService 时,我将 bean 存储到一个带有相应请求对象的 HashMap 中。

dispatcher.put(MyBeanRequest.class, this);
...
((MyAbstractService) dispatcher.get(MyBeanRequest.class).handleRequest(...);

当我在 spring 上下文中搜索 bean 时,它可以工作:

dispatcher.put(MyBeanRequest.class, this.getClass());
...
((MyAbstractService) appContext.getBean(dispatcher.get(requestObject.getClass()))).handleRequest(...);

【讨论】:

    猜你喜欢
    • 2016-10-04
    • 2021-12-24
    • 2022-01-02
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    相关资源
    最近更新 更多