Java中的缓存功能?

Java中的缓存功能?,java,caching,memcached,spring-cache,Java,Caching,Memcached,Spring Cache,我有一个Spring/Java项目,我正在考虑缓存一些访问数据库和其他rest服务的函数。我不确定应该在哪一点缓存某个流。例如,如果我有以下功能: public List<String> getSchools() { //call db to get names } public List<String> getCourses(String school) { //rest call to get courses for a school } pub

我有一个Spring/Java项目,我正在考虑缓存一些访问数据库和其他rest服务的函数。我不确定应该在哪一点缓存某个流。例如,如果我有以下功能:

public List<String> getSchools()
{
     //call db to get names
}

public List<String> getCourses(String school)
{
    //rest call to get courses for a school
}

public List<String> getTeachers(String course)
{
    //call db to get teacher names for a course
}

/*Uses above three functions together*/
public List<String> getAllTeachers()
{
      List<String> schools = getSchools();
      List<String> courses = new ArrayList<String>();
      List<String> teachers = new ArrayList<String>();

      for(String s : schools)
          courses.addAll( getCourses( s ) );
      for(String c : courses)
         teachers.addAll( getTeachers( s ) );

     return teachers;
}
public List getSchools()
{
//调用数据库获取名称
}
公共课程列表(字符串学校)
{
//休息电话为一所学校获取课程
}
公共列表获取教师(字符串课程)
{
//调用db获取课程的教师姓名
}
/*同时使用上述三个功能*/
公共列表getAllTeachers()
{
列出学校=获取学校();
列出课程=新建ArrayList();
列表教师=新建ArrayList();
(s:学校)
课程。添加所有(获取课程);
用于(字符串c:课程)
教师.addAll(getTeachers(s));
归国教师;
}

在这里,我应该缓存哪些方法?我应该缓存调用其他3个资源密集型函数的函数,还是应该单独缓存这三个函数?一般认为什么是良好做法

缓存通常用于不经常更改的数据。
因此,决定是否缓存单个方法的结果vs
getAllTeachers()
取决于与教师/课程/学校相关的数据更改的频率。

我建议缓存单个函数的结果(而不是调用3个方法的另一个函数),并且有一个时间间隔,在此时间间隔之后,当调用该单个函数时,它将丢弃旧数据,并使用来自db的最新数据重新初始化自身。
例如,如果时间间隔为10分钟,则每10分钟对这些函数的调用将返回最新数据。

私有映射函数调用;
私有映射函数resultcache;
长时间间隔=600000//10分钟
公立学校名单
{
if(funcCalls.get(“getSchools”)-currentTimeInMills>=timeGap){
//调用数据库获取名称
}否则{
funcResultCache.get(“getSchools”);
}
}

这种方法的一个缺点是,如果数据在第2分钟发生更改,用户可能会得到过时的数据,但只有在10分钟后才会反映出来。
可以缩短时间间隔以减少这种副作用。

还有一种方法,可能有点麻烦。
假设对数据库的调用将检索大量数据,则
1) 在DML类语句(create/update/delete)的表上有触发器,这些语句将以毫秒为单位写入另一个表中(比如trans_tbl)。
2) 最初存储
变速箱的数据。

3) 在每次调用DB获取实际数据之前,请检查
trans\u tbl
,并检查之前检索到的时间是否大于您拥有的时间。如果“是”,则存储最新时间,然后触发查询以从数据库获取数据。缓存结果并返回相同的结果。


您可以探索的另一个方面是查看您正在使用的数据库本身是否可以缓存“选择”查询。如果“是”,那么这将是一个更简单的方法,因为不需要代码更改,只需调整DB来缓存SELECT查询。

< P>关于<强>这个示例< /强>,我不会考虑缓存,因为数据不会经常改变。br/>
但是,我要做的是: 第一次启动程序时,它应该检索它需要的任何内容,并在数据库中放入一些名为(
changed
)的变量,并将其赋值为0。在服务器端,每当我插入、更新或删除某些内容时,我都会将此
changed
值更改为1。 下次启动应用程序时,它将检索
changed
值,如果值为1,则它将从数据库检索“新”信息,然后返回值0。如果
changed
值已经为0,它将只使用缓存结果

注意你的问题很棘手。因为如果你只将教师、学校和课程加载到内存中,并希望获得例如刚从课程中删除的学生列表(这只是一个示例),那么是否将学生加载到内存中或将其保存在数据库中取决于你

请记住一件简单的事情,当数据库中发生更改时,将该值更改为
1
,然后无论何时从程序中进行查询,都将该值更改回
0


<>最后:为了避免竞争条件,您可能需要考虑从SELECT查询内部将值更新为零。不要等到你完成你的工作,因为你想考虑其他用户使用该应用程序。确保
changed
值在表中,而不是在文件中,使用InnoDB作为存储引擎,因为InnoDB是按行而不是按表锁定的。

您不能使用
addAll()
,因为如果一名教师讲授多个课程,您将有重复的条目。类似的课程(<代码> GigCuthSues()/代码>)如果它们在不同的学校中有相同的名称,您可能需要考虑使用<代码> HASSESET 或<代码> TreSeTinstead@AlanDeep你说得对……但我只是打了个例子。我主要关心的是在哪里使用Spring的缓存抽象。。。。
    private Map<String,Integer> funcCalls;
    private Map<String,List<String>> funcResultCache;
    long timeGap= 600000;//10 mins
    public List<String> getSchools()
    {
       if(funcCalls.get("getSchools")-currentTimeInMills >=timeGap) {
       //call db to get names
       } else {
          funcResultCache.get("getSchools");
       }
    }