首页 文章

Spring引导从bean中的数据库预加载数据

提问于
浏览
2

我要求在一个表中具有递归关系的元素:

child id | parent id

1 |空值

2 | 1

3 | 1

4 | 2

等等......要求整个数据结构需要大约10秒钟,我无法重新设计此表,因为它耗费了太多时间(更多信息:Spring Repository performance issues with recursive ORM Class

现在,我正在考虑在bean的spring启动期间预加载所有数据,以便客户端与bean“通信”并更新bean和数据库中的数据 . 我认为这次启动需要多长时间并不重要,但是用户必须等待多长时间才能解决问题 .

So far, I didn't manage it to preload it. I was trying to create a bean like this:

public class AppConfig extends WebMvcConfigurerAdapter {
...
@Autowired
SkillDAO skillDAO
...
@Bean(name="allSkills")
public List<Skill> allSkills(){
    return skillDAO.findBySkill(null);
}
...

它不起作用导致我收到错误:

引起:org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名为'dataSource'的bean时出错:请求的bean当前正在创建中:是否存在无法解析的循环引用?

顺便说一下,我在AppConfig中创建了所有的bean . 当我删除这个“allSkills”bean时,它再次起作用 .

UPDATE

@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();
}

2 回答

  • 3

    Cache 会优雅地解决您的需求 .

    理想情况下,你会有一个 Service ,它有一个返回技能的方法 .

    这个方法可以这样解释:

    import org.springframework.cache.annotation.Cacheable;
    
    @Cacheable(value = "skills", key = "#root.methodName")
    public List<Skill> getAllSkills() {
        return ... your skills ...;
    }
    

    要在Spring Boot中启用缓存,请将 @EnableCaching 注释添加到配置类,并添加 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 只是在第一次调用时执行一次,然后在没有调用方法的情况下从缓存管理器返回值 .

  • 2

    您可以侦听ApplicationReadyEvent,然后调用该方法(来自@ yglodt的answer)来初始化您的缓存 .

    示例代码:

    @Component
    public class MyEventsListener {
    
        @Autowired
        SkillsService skillsService;
    
        @EventListener
        public void onApplicationReady(ApplicationReadyEvent ready) {
            skillsService.getAllSkills();
        }
    }
    

    还要记住,如果从SkillsService bean本身调用 getAllSkills() ,则不会访问缓存,因为只有在类的注入proxy上调用该方法时才会建议该方法 .

    如果您将应用程序部署为可执行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();
        }
    
    }
    

相关问题