Spring 引导从 bean 中的数据库预加载数据
Spring boot preloading data from database in bean
我要的是在一个元素中具有递归关系的元素 table:
child ID | parent id
1 |空
2 | 1
3 | 1
4 | 2
等等...请求整个数据结构大约需要 10 秒目前我无法重新设计这个 table 因为它花费了太多时间(更多信息:)
现在,我正在考虑在 bean spring 启动期间预加载所有数据,以便使用 bean 的客户端 "communicates" 和我更新 bean 和数据库中的数据。我认为这个启动需要多长时间并不重要,重要的是用户需要等待它的答案多长时间。
到目前为止,我还没有设法预加载它。我试图创建一个这样的 bean:
public class AppConfig extends WebMvcConfigurerAdapter {
...
@Autowired
SkillDAO skillDAO
...
@Bean(name="allSkills")
public List<Skill> allSkills(){
return skillDAO.findBySkill(null);
}
...
它不起作用,因为我得到一个错误:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?
顺便说一下,我在 AppConfig 中创建了所有 bean。当我删除这个 "allSkills" bean 时,它再次工作。
更新
@Component
public class MyListener {
@Autowired
private SkillDAO skillDAO;
@EventListener
public void onApplicationReady(ApplicationReadyEvent ready) {
System.out.println("++++++++++++++ HALLO +++++++++++++");
skillDAO.findBySkill(null);
}
}
...
@Bean(name="skillBean")
public MyListener myListener() {
return new MyListener();
}
一个Cache
可以优雅地解决你的需求。
理想情况下,您会拥有一个 Service
具有 returns 技能的方法。
此方法可能如下所示:
import org.springframework.cache.annotation.Cacheable;
@Cacheable(value = "skills", key = "#root.methodName")
public List<Skill> getAllSkills() {
return ... your skills ...;
}
要在 Spring 引导中启用缓存,请将 @EnableCaching
注释添加到您的配置 class,然后添加 Bean
进行配置:
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("skills", "othercachename");
}
这样,方法 getAllSkills
只执行一次,第一次被调用,然后从缓存管理器返回值,甚至没有调用该方法。
您可以侦听 ApplicationReadyEvent
, and then call the method (from @yglodt's ) 以初始化您的缓存。
示例代码:
@Component
public class MyEventsListener {
@Autowired
SkillsService skillsService;
@EventListener
public void onApplicationReady(ApplicationReadyEvent ready) {
skillsService.getAllSkills();
}
}
还要记住,如果您从 SkillsService bean 本身内部调用 getAllSkills()
,您将不会命中缓存,因为该方法仅在调用 proxy 的class.
如果您将应用程序部署为可执行 jar(而不是 war 文件),那么最简单的解决方案是在启动时调用您想要 运行 的代码来自你的 main method:
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
SkillsService skillsService = context.getBean(SkillsService.class);
skillsService.getAllSkills();
}
}
我要的是在一个元素中具有递归关系的元素 table:
child ID | parent id
1 |空
2 | 1
3 | 1
4 | 2
等等...请求整个数据结构大约需要 10 秒目前我无法重新设计这个 table 因为它花费了太多时间(更多信息:
现在,我正在考虑在 bean spring 启动期间预加载所有数据,以便使用 bean 的客户端 "communicates" 和我更新 bean 和数据库中的数据。我认为这个启动需要多长时间并不重要,重要的是用户需要等待它的答案多长时间。
到目前为止,我还没有设法预加载它。我试图创建一个这样的 bean:
public class AppConfig extends WebMvcConfigurerAdapter {
...
@Autowired
SkillDAO skillDAO
...
@Bean(name="allSkills")
public List<Skill> allSkills(){
return skillDAO.findBySkill(null);
}
...
它不起作用,因为我得到一个错误:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?
顺便说一下,我在 AppConfig 中创建了所有 bean。当我删除这个 "allSkills" bean 时,它再次工作。
更新
@Component
public class MyListener {
@Autowired
private SkillDAO skillDAO;
@EventListener
public void onApplicationReady(ApplicationReadyEvent ready) {
System.out.println("++++++++++++++ HALLO +++++++++++++");
skillDAO.findBySkill(null);
}
}
...
@Bean(name="skillBean")
public MyListener myListener() {
return new MyListener();
}
一个Cache
可以优雅地解决你的需求。
理想情况下,您会拥有一个 Service
具有 returns 技能的方法。
此方法可能如下所示:
import org.springframework.cache.annotation.Cacheable;
@Cacheable(value = "skills", key = "#root.methodName")
public List<Skill> getAllSkills() {
return ... your skills ...;
}
要在 Spring 引导中启用缓存,请将 @EnableCaching
注释添加到您的配置 class,然后添加 Bean
进行配置:
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("skills", "othercachename");
}
这样,方法 getAllSkills
只执行一次,第一次被调用,然后从缓存管理器返回值,甚至没有调用该方法。
您可以侦听 ApplicationReadyEvent
, and then call the method (from @yglodt's
示例代码:
@Component
public class MyEventsListener {
@Autowired
SkillsService skillsService;
@EventListener
public void onApplicationReady(ApplicationReadyEvent ready) {
skillsService.getAllSkills();
}
}
还要记住,如果您从 SkillsService bean 本身内部调用 getAllSkills()
,您将不会命中缓存,因为该方法仅在调用 proxy 的class.
如果您将应用程序部署为可执行 jar(而不是 war 文件),那么最简单的解决方案是在启动时调用您想要 运行 的代码来自你的 main method:
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
SkillsService skillsService = context.getBean(SkillsService.class);
skillsService.getAllSkills();
}
}