有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

子id |父id

1 |空

2 | 1

3 | 1

4 | 2

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

现在,我考虑在spring启动期间将所有数据预加载到bean中,以便客户机与bean“通信”,我更新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();
}

共 (2) 个答案

  1. # 1 楼答案

    您可以侦听^{},然后调用该方法(从@yglott的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();
        }
    
    }
    
  2. # 2 楼答案

    一个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在第一次调用时只执行一次,然后从缓存管理器返回值,甚至不调用该方法