首页 > 解决方案 > 使用 Java Streams 和 Spring Boot 的 RESTful Web 服务

问题描述

我尝试实现一个 RESTful WebService,它能够直接从数据库中流式传输数百万条记录。我正在使用 SpringBoot 2.2.5、Hibernate 5 和 PostgreSQL 11

根据这篇文章: https ://www.airpair.com/java/posts/spring-streams-memory-efficiency

需要一步将标志“allowResultAccessAfterCompletion”设置为真。但是我怎么能在 Spring Boot 中做到这一点?

到目前为止,我的应用程序中没有任何 SessionFactory、EntityManagerFactory、Datasource 等配置。一切都是由 SpringBoot 自动配置的。

如果我在下面添加建议的配置,由于缺少 SessionFactory,应用程序将无法启动。

@Configuration
@EnableTransactionManagement
public class DataConfig {

  @Autowired @Bean
  public PlatformTransactionManager txManager(SessionFactory sf) {
    HibernateTransactionManager mgr = new HibernateTransactionManager(sf);
    mgr.setAllowResultAccessAfterCompletion(true);
    return mgr;
  }
  ... (the rest of your data config, including the LocalSessionFactoryBean) ...
}

如果我通过从 EntityManagerFactory 解包它来提供 SessionFactory bean,我会得到另一个异常:

通过字段 'entityManagerFactory' 表达的不满足的依赖关系;嵌套异常是 org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名为“getSessionFactory”的 bean 时出错:当前正在创建请求的 bean:是否存在无法解析的循环引用?

有人对我的设置有有效的配置吗?

这个标志不能简单地由 application.properties 中的一些配置值设置吗?

谢谢!

标签: javaspring-boothibernatespring-transactionstransactionmanager

解决方案


首先,您需要决定是否需要为您的项目使用 Hibernate 或 Spring JPA。使用框架而不是反对它。今天大多数人更喜欢使用 jpa 类而不是 hibernate 类。由于您使用的是 springboot ,因此最好的方法是使用框架并使用spring-boot-starter-data-jpa它将在启动时自动配置所有必要的 bean。在这种情况下,您可以提供自己的自定义 bean 来根据需要覆盖参数。

在您在问题中提供的示例代码中,您直接使用 Hibernate 类,因此您必须手动创建所有必要的 bean,因为除非您禁用可能导致的自动配置,否则 spring 将无法与您一起工作您的循环依赖问题。

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("com.sample.spring.repository")
@PropertySource("classpath:database.properties")

public class DataConfig {

    private final String PROPERTY_DRIVER = "driver";
    private final String PROPERTY_URL = "url";
    private final String PROPERTY_USERNAME = "user";
    private final String PROPERTY_PASSWORD = "password";
    private final String PROPERTY_SHOW_SQL = "hibernate.show_sql";
    private final String PROPERTY_DIALECT = "hibernate.dialect";

    @Autowired
    Environment environment;

    @Bean
    LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean lfb = new LocalContainerEntityManagerFactoryBean();
        lfb.setDataSource(dataSource());
        lfb.setPersistenceProviderClass(HibernatePersistence.class);
        lfb.setPackagesToScan("com.sample.spring");
        lfb.setJpaProperties(hibernateProps());
        return lfb;
    }

    @Bean
    DataSource dataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setUrl(environment.getProperty(PROPERTY_URL));
        ds.setUsername(environment.getProperty(PROPERTY_USERNAME));
        ds.setPassword(environment.getProperty(PROPERTY_PASSWORD));
        ds.setDriverClassName(environment.getProperty(PROPERTY_DRIVER));
        return ds;
    }

    Properties hibernateProps() {
        Properties properties = new Properties();
        properties.setProperty(PROPERTY_DIALECT, environment.getProperty(PROPERTY_DIALECT));
        properties.setProperty(PROPERTY_SHOW_SQL, environment.getProperty(PROPERTY_SHOW_SQL));
        return properties;
    }

    @Bean
    JpaTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }
}

 

推荐阅读