【问题标题】:Needs clarity on hibernate second level cache需要清晰的休眠二级缓存
【发布时间】:2012-10-12 14:04:39
【问题描述】:

我需要对 Hibernate 二级缓存进行一些说明。

  1. 休眠二级缓存是如何工作的?

  2. 在 Java EE 环境中启动服务器的实体类中,是否从有@Cacheable 注释(相对于休眠注释)的表中加载所有数据?

  3. 当这些表有更新时缓存是否会同步?如何同步?

  4. 最后一个是否有任何方法可以让我的 DAO 代码在我感兴趣的某个表有更新时得到通知? (寻找任何可以密切关注表格更新的听众)。

【问题讨论】:

    标签: java hibernate caching memcached


    【解决方案1】:
    1. hibernate 二级缓存是如何工作的?

      当您的实体被标记为可缓存并且您已配置二级缓存时,休眠将在第一次读取后将该实体缓存到二级缓存。

      Hibernate 提供了插入任何遵循 hibernate 规范的缓存实现的灵活性。有关二级缓存和配置选项的更多详细信息,请参阅Hibernate Manual

    2. 它是否从 Java EE 环境中启动的服务器上的实体类中加载有@Cacheable 注释(相对于休眠注释)的表中的所有数据?

      我认为没有任何配置可以实现这一点。间接地,您可以通过在启动时读取整个表来实现这一点,这会对系统启动时间产生不利影响。 (我不喜欢这个)。如果实体被外部修改,则休眠无法同步它,您最终会得到陈旧的数据。

    3. 当这些表有更新时缓存会同步吗?

      表更新后缓存不会立即更新。获取更新记录的后续调用将进入数据库,hibernate 通过使用会话时间戳在内部实现这一点。

    4. 最后一个有什么方法可以让我的 DAO 代码在我感兴趣的某个表上有更新时得到通知? (寻找任何可以了解表更新的监听器)。

      不,hibernate 不支持这个。

    【讨论】:

    • 感谢您的详细解答。所以应该有一个明确的校准时间来从表中读取更新的数据并且休眠实习生在内部更新缓存?我在我的应用程序中使用二级缓存,并在 cfg.xml 文件中使用“Show_SQL = true”,每当我多次调用相同的方法时,它都会打印查询。这是否意味着它只是在控制台上打印查询,但它从缓存中获取数据?无论如何要验证或检查从哪里获取数据(无论是从数据库还是缓存)?
    • 如果它显示 SQL,它正在执行它。如果您正在执行查询,而不仅仅是调用 Session.get() 或导航 toOne 关联,那么它将始终执行 SQL 查询,除非查询本身是可缓存的并且启用了查询缓存。
    • 我没有在我的应用程序中启用查询缓存,我主要使用 hql 查询。每次我调用同一个方法时,它都会执行查询——这意味着每次它访问数据库以获取数据 r8t?但是当我打印每次迭代所花费的时间时,它会不断减少。这就是为什么我对数据是从数据库还是缓存中提取感到困惑的原因
    • 是的,每次都进入数据库。 Buta 数据库速度很快,因为它们还具有缓存、优化等功能。这就是您看到时间减少的原因。
    • 如果您将“hibernate.show_sql”设置为“true”,您将始终看到打印的查询。为了验证数据是否来自缓存/数据库,您可能需要通过 JMX 依赖缓存统计信息。 1.在你的cahce中启用统计,参考Ehcache Documentation。 2.在平台MBean服务器中注册CacheStatistics,参考Ehcache Documentation
    【解决方案2】:
    1. 这是一个太宽泛的问题,无法在这里回答。

    2. 没有。它懒惰地填充缓存。每次您使用 hibernate API 或查询从数据库中获取可缓存实体时,该实体都会存储在缓存中。稍后,当session.get() 使用缓存中的实体的ID 调用时,不需要进行数据库查询。

    3. 如果通过 Hibernate 进行更新,则更新缓存。如果它是使用外部应用程序、SQL 查询,甚至是批量更新 HQL 查询完成的,那么缓存将不知道更新。这就是为什么您需要注意使哪些实体可缓存、选择哪些生存时间等。有时,返回陈旧值没有问题,但有时它是不可接受的。

    4. 没有。

    【讨论】:

    • 感谢您的回答。只有当我第二次通过 ID 进行查询时,它才会尝试从缓存而不是数据库中获取数据?我在我的应用程序中使用二级缓存,并在 cfg.xml 文件中使用“Show_SQL = true”,每当我多次调用相同的方法时,它都会打印查询。这是否意味着它只是在控制台上打印查询,但它从缓存中获取数据?有没有办法验证或检查从哪里获取数据(无论是从数据库还是缓存)?
    • 是的,缓存仅在通过 ID 访问实体时使用(使用 session.get() 或通过 toOne 关联导航)
    猜你喜欢
    • 2017-07-05
    • 2010-10-20
    • 2017-10-07
    • 2011-07-08
    • 1970-01-01
    • 2010-10-29
    • 2019-04-02
    • 2023-03-03
    相关资源
    最近更新 更多