java - 使用 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 中的一些配置值设置吗?
谢谢!
解决方案
首先,您需要决定是否需要为您的项目使用 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;
}
}