简体   繁体   中英

How to cache data during application startup in Spring boot application

I have a Spring boot Application connecting to SQL Server Database. I need some help in using caching in my application. I have a table for CodeCategory which has a list of codes for Many codes. This table will be loaded every month and data changes only once in a month. I want to cache this entire table when the Application starts. In any subsequent calls to the table should get value from this cache instead of calling the Database.

For Example,

List<CodeCategory> findAll();

I want to cache the above DB query value during application startup. If there is a DB call like List<CodeCategory> findByCodeValue(String code) should fetch the code result from the already Cached data instead of calling the Database.

Please let me know how this can be achieved using spring boot and ehcache.

Use the second level hibernate caching to cache all the required db queries.

For caching at the application start-up, we can use @PostContruct in any of the Service class.

Syntax will be :-

@Service
public class anyService{

  @PostConstruct
  public void init(){
     //call any method
 }
}

As pointed out, It takes some time for ehcache to setup and it is not working completely with @PostConstruct . In that case make use of ApplicationStartedEvent to load the cache.

GitHub Repo: spring-ehcache-demo


@Service
class CodeCategoryService{

   @EventListener(classes = ApplicationStartedEvent.class )
   public void listenToStart(ApplicationStartedEvent event) {
        this.repo.findByCodeValue("100");
   }

}

interface CodeCategoryRepository extends JpaRepository<CodeCategory, Long>{

    @Cacheable(value = "codeValues")
    List<CodeCategory> findByCodeValue(String code);
}


Note: There are multiple ways as pointed by others. You can choose as per your needs.

Use CommandLineRunner interface. Basically , you can create a Spring @Component and implement CommandLineRunner interface. You will have to override it's run method. The run method will be called at the start of the app.

@Component
public class DatabaseLoader implements 
CommandLineRunner {

   @override
   Public void run(.... string){
     // Any code here gets called at the start of the app.
  }}

This approach is mostly used to bootstrap the application with some initial data.

My way is to define a generic cache handler

@FunctionalInterface
public interface GenericCacheHandler {

List<CodeCategory> findAll();
 }

And its implementation as below

@Component
@EnableScheduling  // Important
public class GenericCacheHandlerImpl implements GenericCacheHandler {

@Autowired
private CodeRepository codeRepo;

private List<CodeCategory> codes = new ArrayList<>();

@PostConstruct
private void intializeBudgetState() {
    List<CodeCategory> codeList = codeRepo.findAll();
    // Any customization goes here
    codes = codeList;
}

@Override
public List<CodeCategory> getCodes() {
    return codes;
}
}

Call it in Service layer as below

@Service
public class CodeServiceImpl implements CodeService {

@Autowired
private GenericCacheHandler genericCacheHandler;

@Override
public CodeDTO anyMethod() {
    return genericCacheHandler.getCodes();
}   
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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