Java缓存和动态更新

发布于 2024-12-29 21:05:22 字数 254 浏览 0 评论 0原文

我需要在 servlet 启动时从数据库“预加载”一些数据。

所以我想创建一些缓存,例如使用 HashMap 或一些类似的同步版本。

我还需要在数据库更新更改时更新缓存。
所以我想添加某种“监听器”。

我的问题是:这是否可用,或者我是否必须实际实施它?

如果是,哪种设计模式是最好的方法?

更新:
未使用 JPA 或 ORM。但春天可以

I need to "preload" some data from a database on servlet startup.

So I thought to create some cache e.g. using a HashMap or some similar synchronized version.

I also need to update the cache on database update changes.
So I thought to add some kind of "listener".

My question is: is this somehow available or do I have to actually implement it?

If yes what design pattern would be the best approach here?

Update:
No JPA or ORM used. But Spring is available

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

日记撕了你也走了 2025-01-05 21:05:22

是的,当然你可以实现
我会画一个小架构然后给你解释一下:

架构图

首先,你可以了解Mappers < a href="http://martinfowler.com/eaaCatalog/dataMapper.html" rel="nofollow noreferrer">此处 和 TDG 此处
映射器有一个名为 cacheAll() 的方法,该方法调用并委托给 TDG 的方法 cacheAll(),而后者的任务是从数据库的表中获取所有行(您想要在缓存对象中缓存的行)。

所以基本上首先你必须创建一个实现 "ServletContextListener" 的监听器
这意味着它是整个 servlet 上下文的侦听器,并且在其 contextInitialized 内,您必须调用 mp.fill(Mapper.cacheAll()),所以它就像 (这是一般代码,当然要写得更好并优化它)

public class myServletContextListener implements ServletContextListener{

@Override
public void contextInitialized(ServletContextEvent sce) {
        mp.fill(Mapper.cacheAll());
 }

//
}

不要忘记在 web.xml 中添加监听器:

<listener>
    <listener-class>myServletContextListener </listener-class>
</listener>

所以这将在服务器启动时将所有记录缓存到 hashmap mp 中缓存对象。

至于根据数据库更改更新缓存,您必须使用

更新
我忘了提及,关于缓存对象,我假设您希望所有用户或您的应用程序都可以访问它,因此您应该将其编码为单例(单例模式),代码如下:

 public class cacheObject
{
    private static Map cMap;
    private static cacheObject cObject;
    private cacheObject()
    {
        cMap = Mapper.cacheAll();
    }
    public static synchronized cacheObject getInstance()
    {
        if (cObject == null){
            cObject = new cacheObject();
        }
        return cObject;
    }

}

此外,如果您要缓存的数据可以由用户更改,因此使其成为Threadlocal单例。

Yes of course you can implement that
I'll draw a small architecture then ill explain it to u:

Architecture diagram

first of all , you can learn about Mappers here and TDGs here.
A mapper has a method called cacheAll() which calls and delegate to TDG's method cacheAll() which in its turn has a mission to get all rows from a table from the db( the rows you want to cache in the cache object).

so basically first you have to create a listener implementing "ServletContextListener"
which means its a listener for the whole servlet context, and inside its contextInitialized you have to call mp.fill(Mapper.cacheAll()), so it is sthg like ( this is general code, of course write it better and optimize it)

public class myServletContextListener implements ServletContextListener{

@Override
public void contextInitialized(ServletContextEvent sce) {
        mp.fill(Mapper.cacheAll());
 }

//
}

Don't forget to add your listener in web.xml:

<listener>
    <listener-class>myServletContextListener </listener-class>
</listener>

so what this will do , is on startup of the server, will cache all record into a hashmap mp in a cache object.

As for updating cache based on database change, you will have to use observer pattern.

UPDATE
I forgot to mention, about the cache object, i assume you want it accessible for all users or your app, so you should code it as a singleton (singleton pattern), code like that:

 public class cacheObject
{
    private static Map cMap;
    private static cacheObject cObject;
    private cacheObject()
    {
        cMap = Mapper.cacheAll();
    }
    public static synchronized cacheObject getInstance()
    {
        if (cObject == null){
            cObject = new cacheObject();
        }
        return cObject;
    }

}

Also if the data that you want to cache can be changed by users, so make it a Threadlocal singleton.

伤痕我心 2025-01-05 21:05:22

您可能会发现 Guava 可以最好地满足您的需求。关于缓存的 wiki文章可能与您最相关,但确切的内容这里的方法在很大程度上取决于数据库更新更改的条件。如果您想在数据库更新更改时刷新整个缓存 - 或者至少使旧条目无效 - 您可以在数据库更新发生时调用 Cache.invalidateAll() 。如果您愿意让缓存稍微落后于时代,那么使用 CacheBuilder.refreshAfterWrite(long, TimeUnit) 可能会很适合您。

You may find your needs served best by Guava here. The wiki article on Caches is probably most relevant to you, but the exact approach here would depend heavily on the conditions for database update changes. If you want to refresh the whole cache on database update changes -- or at least invalidate old entries -- you might just call Cache.invalidateAll() whenever a database update occurs. If you're willing to let the cache be only slightly behind the times, using CacheBuilder.refreshAfterWrite(long, TimeUnit) might work well for you.

静谧幽蓝 2025-01-05 21:05:22

Hashmap 及其线程安全变体 ConcurrentHashMap 已经可用。

有一些可用的缓存解决方案,例如 ehcache,它还提供高级支持,例如驱逐策略等等。

至于设计模式,请阅读观察者设计模式。

Hashmap and it's thread safe variant ConcurrentHashMap is already available.

There are caching solutions which are available like ehcache which also provide advanced support like eviction policies and many more things.

As for the design pattern, read into the Observer design pattern.

回忆凄美了谁 2025-01-05 21:05:22

我实际上有一个生产级别的项目,我需要做这样的事情。我的解决方案是(这只是我的解决方案)是在 servlet 启动时将对象(您的“数据”)加载到内存中。做出这个决定是因为该对象足够大,导致客户端从数据库中提取该对象的请求变得缓慢,而且我的并发用户数量很少。任何会更改数据库中该对象数据的请求也会更改内存中的对象。如果您正在与很多用户一起工作,您当然需要使用同步对象来执行此操作。如果数据量不大,那么每次用户请求有关数据的信息时,您总是可以从数据库中提取数据。

祝你好运。

I actually had a production level project where I needed to do something like this. My solution was (and this is just MY solution) was to load the object (your so "data") into memory at servlet start up. This decision was made because the object was large enough that it made client requests sluggish to pull it from the database AND I had a small number of concurrent users. Any requests that would change that object's data in the database would also change the in-memory object. You of course would need to use a synchronized object to do this if you are working with a lot of users. If the amount of data is not huge, then you could always pull from the database every time the user requests information about the data.

Good Luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文