简体   繁体   English

Spring Boot从Bean中的数据库预加载数据

[英]Spring boot preloading data from database in bean

I'm asking for elements that have a recursive relationship in one table: 我要的是在一个表中具有递归关系的元素:

child id | 儿童编号| parent id 家长编号

1 | 1 | null 空值

2 | 2 | 1 1

3 | 3 | 1 1

4 | 4 | 2 2

And so on...To ask for this whole datastructure it takes about 10 secondsAt the moment I can't redesign this table because it cost too much time (for more information: Spring Repository performance issues with recursive ORM Class ) 依此类推...要花费整个数据结构大约10秒钟的时间,目前我无法重新设计该表,因为它花费了太多时间(有关更多信息: 递归ORM类的Spring Repository性能问题

Now, I am thinking about preloading all data during spring startup in a bean, so that the client "communicates" with the bean and I update the data in bean and database. 现在,我正在考虑在春季启动期间将所有数据预加载到Bean中,以便客户端与Bean“通信”,并更新Bean和数据库中的数据。 I think it doesn't matter how long this startup takes, but it matters how long the user has to wait for its answer. 我认为启动需要多长时间无关紧要,但是用户必须等待多长时间才有意义。

So far, I didn't manage it to preload it. 到目前为止,我还没有对其进行预加载。 I was trying to create a bean like this: 我试图创建一个像这样的bean:

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

It doesn't work cause I get an error: 它不起作用,因为出现错误:

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? 原因:org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'dataSource'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用?

By the way, I create all my beans in AppConfig. 顺便说一下,我在AppConfig中创建了所有的bean。 When I delete this "allSkills" bean, it works again. 当我删除此“ allSkills” bean时,它又可以工作了。

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

You can listen for the ApplicationReadyEvent , and then call the method (from @yglodt's answer ) to initialise your cache. 您可以侦听ApplicationReadyEvent ,然后调用方法(来自@yglodt的answer )以初始化缓存。

Example code: 示例代码:

@Component
public class MyEventsListener {

    @Autowired
    SkillsService skillsService;

    @EventListener
    public void onApplicationReady(ApplicationReadyEvent ready) {
        skillsService.getAllSkills();
    }
}

Also remember that if you call getAllSkills() from within the SkillsService bean itself, you will not hit the cache, because the method is only advised when it is called on an injected proxy of the class. 还要记住,如果您从SkillsService bean本身内部调用getAllSkills() ,则不会访问缓存,因为仅在对该类的注入代理上调用该方法时才建议使用该方法。

If you're deploying the application as an executable jar (rather than a war file), then the simplest solution is to invoke the code that you want to run at start-up from your main method : 如果要将应用程序部署为可执行jar(而不是war文件),那么最简单的解决方案是从您的main方法调用要在启动时运行的代码:

public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        SkillsService skillsService = context.getBean(SkillsService.class);
        skillsService.getAllSkills();
    }

}

A Cache would solve your requirement elegantly. Cache可以轻松解决您的需求。

Ideally you would have a Service which has a method which returns the skills. 理想情况下,您将拥有一个可以返回技能的方法的Service

This method could looke like this: 该方法看起来像这样:

import org.springframework.cache.annotation.Cacheable;

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

To enable Caching in Spring Boot, add the @EnableCaching annotation to your configurations class, and add a Bean to configure it: 要在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");
}

This way, the method getAllSkills is just executed once, the first time it's called, and afterwards the values are returned from the cache-manager without even calling the method. 这样,方法getAllSkills只会在第一次调用时执行一次,然后从缓存管理器返回值,甚至不调用该方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM