何时以及如何使用hibernate二级缓存? [英] When and how to use hibernate second level cache?

查看:115
本文介绍了何时以及如何使用hibernate二级缓存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



这是我目前了解的内容:




  • 二级缓存存储会话之间的实体,范围是SessionFactory

  • 必须告诉要缓存哪些实体,将默认缓存

  • 查询缓存将查询结果存储在缓存中。



我不明白的是


  • 什么时候hibernate打这个缓存?

  • 假设我设置了二级缓存,但没有设置查询缓存。我想缓存我的客户,其中有50000个。我可以通过哪些方式从缓存中检索客户?

  • 我假设我可以通过缓存中的id来获取它们。这很容易,但也不值得高速缓存。但是如果我想和我的所有客户进行一些计算呢。假设我想展示客户名单,那么我将如何访问他们?

  • 如果查询缓存被禁用,我将如何获得所有客户?

  • 如果有人更新了其中一位顾客,会发生什么情况?


    • 该客户是否会在缓存中失效或所有客户失效?




或者我认为缓存完全错误?在这种情况下,更适合使用二级缓存的是什么? hibernate文档根本不清楚缓存如何在现实中工作。只有关于如何设置它的说明。



更新:
所以我明白了第二层缓存(不含查询缓存)对于通过id加载数据来说非常有用。例如,我有一个用户对象,我想检查Web应用程序中每个请求的权限。通过将用户缓存在二级缓存中来减少数据库访问会是一个很好的例子吗?就像我会将用户ID存储在会话中或任何时候需要检查权限时一样,我会通过它的id和检查权限来加载用户。

解决方案

首先,让我们讨论一下进程级别的缓存(或者是他们在Hibernate中调用它的二级缓存)。为了使它工作,您应该


  1. 配置缓存提供程序
  2. 告诉hibernate要缓存的实体如果你使用这种映射,就在hbm.xml文件中)。

您告诉缓存提供者它应该存储多少个对象以及何时/为什么它们应该失效。假设你有一本书和一个作者实体,每次你从数据库中获取它们,只有那些不在缓存中的实际数据库才会被选中。这大大提高了性能。这在以下情况下很有用:


  • 您只通过Hibernate写入数据库(因为它需要一种方法来知道何时更改或使缓存)

  • 您经常阅读对象

  • 您有单个节点,并且没有复制。否则,您需要复制缓存本身(使用像JGroups这样的分布式缓存),这会增加更多的复杂性,并且不会像无共享应用那样扩展。



所以当缓存工作的时候?




  • session.get() 或 session.load()先前选择并驻留在缓存中的对象。缓存是一个存储,其中ID是密钥,属性是值。因此,只有当有可能通过ID进行搜索时,才能消除数据库。

  • 当您的关联延迟加载(或用选择而非连接加载时)
  • >


但在以下情况下无效:


  • 如果你没有通过ID选择。再次 - 二级缓存将实体ID的映射存储到其他属性(它实际上不存储对象,但数据本身),因此如果您的查找如下所示:来自作者where name =

  • 当您使用HQL时(即使您使用其中id =?)。

  • 如果在映射中设置 fetch =join,这意味着加载关联连接将被使用而不是分开选择语句。仅当使用 fetch =select时,进程级高速缓存才能用于子对象。

  • 即使您有 fetch =select但在HQL中使用连接来选择关联 - 这些连接将立即发出,它们将覆盖您在hbm.xml或注释中指定的任何内容。



现在,关于查询缓存。你应该注意到它不是一个单独的缓存,它是对进程级缓存的补充。假设你有一个国家实体。它是静态的,所以你知道每次当你从国家时都会有相同的结果集。这是查询缓存的完美候选者,它将自己存储一个 ID 的列表,并且当您下次选择所有国家时,它会将此列表返回到进程级别缓存,而后者将依次返回,将返回每个ID的对象,因为这些对象已经存储在二级缓存中。
每当任何与实体相关的变化发生时,查询缓存都会失效。假设您将作者中的配置到查询缓存中。由于作者经常更改,因此这不会有效。所以你应该只使用查询缓存来处理更多或更少的静态数据。


I have trouble understanding when hibernate hits the second level cache and when does it invalidate the cache.

This is what I currently understand:

  • Second level cache stores entities between sessions, scope is the SessionFactory
  • You have to tell which entities to cache, no entity will get cached by default
  • Query cache stores results of queries in the cache.

What I don't understand is

  • When does hibernate hit this cache?
  • Let's say I've set up the second level cache but not the query caching. I want to cache my customers, there's 50000 of them. In what ways can I retrieve the customers from the cache?
  • I assume I can get them by id from cache. That would be easy but also not worthy of caching. But what if I want to do some calculation with all my customers. Let's say I want to show a list of the customers then how would I access them?
  • How would I get all my customers if query caching is disabled?
  • What would happen if someone updated one of the customers?
    • Would that customer get invalidated in the cache or would all customers get invalidated?

Or am I thinking caching totally wrong? What would be more appropriate uses of second level cache in that case? The hibernate documentation is not at all clear how the cache works in reality. There are only instructions on how to get it set up.

Update: So I've come to understand that second level cache(without query cache) would be good for loading data by id's. For example I have user object that I want to check for permissions in every request in a web application. Would this be a good case to reduce database access by caching the user in the second level cache? Like I would store the user id in the session or wherever and when I need to check for permissions I would load the user by it's id and check permissions.

解决方案

First of all, let's talk about process level cache (or 2nd level cache as they call it in Hibernate). To make it work, you should

  1. configure cache provider
  2. tell hibernate what entities to cache (right in hbm.xml file if you use this kind of mapping).

You tell to the cache provider how many objects it should store and when/why they should be invalidated. So let's say you have a Book and an Author entities, each time you're getting them from the DB, only those that are not in cache will be selected from actually DB. This increases performance significantly. It's useful when:

  • You write to the database only via Hibernate (because it needs a way to know when to change or invalidate entities in the cache)
  • You read objects often
  • You have a single node, and you don't have replication. Otherwise you'll need to replicate the cache itself (use distributed caches like JGroups) which adds more complexity, and it doesn't scale as good as share-nothing apps.

So when does cache work?

  • When you session.get() or session.load() the object that was previously selected and resides in cache. Cache is a storage where ID is the key and the properties are the values. So only when there is a possibility to search by ID you could eliminate hitting the DB.
  • When your associations are lazy-loaded (or eager-loaded with selects instead of joins)

But it doesn't work when:

  • If you don't select by ID. Again - 2nd level cache stores a map of entities' IDs to other properties (it doesn't actually store objects, but the data itself), so if your lookup looks like this: from Authors where name = :name, then you don't hit cache.
  • When you use HQL (even if you use where id = ?).
  • If in your mapping you set fetch="join", this means that to load associations joins will be used everywhere instead of separate select statements. Process level cache works on children objects only if fetch="select" is used.
  • Even if you have fetch="select" but then in HQL you use joins to select associations - those joins will be issued right away and they will overwrite whatever you specified in hbm.xml or annotations.

Now, about Query Cache. You should note that it's not a separate cache, it's an addition to the process level cache. Let's say you have a Country entity. It's static, so you know that each time there will be the same result set when you say from Country. This is a perfect candidate for query cache, it will store a list of IDs in itself and when you next time select all countries, it will return this list to the process level cache and the latter, in turn, will return objects for each ID as these objects are stored already in the 2nd level cache. Query cache is invalidated each time anything related to the entity changes. So let's say you configured from Authors to be placed into a Query Cache. It won't be effective as Author changes often. So you should use Query Cache only for more or less static data.

这篇关于何时以及如何使用hibernate二级缓存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆