# 使用 Hibernate 4 进行缓存

> 原文： [https://javabeginnerstutorial.com/hibernate/caching-with-hibernate-4/](https://javabeginnerstutorial.com/hibernate/caching-with-hibernate-4/)

如果您有更大的应用，则应考虑性能以及如何提高性能。 缓存是执行此操作的一种方法，因为它可以减少对数据库的查询。 查询数据库始终会对性能产生影响，因为它是 I/O 操作。 而且 I/O 操作比仅使用应用内存的操作要慢得多。

缓存在您的应用和数据库之间起作用，以尽可能避免数据库命中次数。

## 实体缓存

默认情况下，Hibernate 使用第一级缓存，这意味着它将通过会话将实体存储在应用的内存中（为 Hibernate 分配）。 它是所有实体都必须传递的强制性缓存。 这有两个好处：如果经常访问该实体，则 Hibernate 会记住它；如果您的应用再次需要该实体，则将从会话的缓存中返回它； 第二个好处是，如果您在一个实体上执行多个更新，则 Hibernate 尝试将这些更新分组在一起，并延迟实际的数据库调用以减少 I/O 流量。 如果关闭会话，则存储在第一级缓存中的对象将被销毁并保存或更新到数据库。

您可以使用可选的二级缓存来扩展此缓存。 一级始终是强制性的，始终会首先被咨询。 二级缓存用于跨会话缓存对象。 对于二级缓存，有一些第三方解决方案可以与 Hibernate 一起使用。 Hibernate 提供了`org.hibernate.cache`。 提供程序必须实现`CacheProvider`接口，以使 Hibernate 处理缓存。

市场上有一些缓存提供程序，但是 Hibernate 希望您为整个应用选择一个提供程序。

让我提及一些缓存提供程序：

*   高速缓存
*   OS 缓存
*   Infinispan

在上面提到的那些之外，EHCache 是​​最流行和广泛使用的。

### 缓存策略

使用二级缓存时，必须记住一些缓存策略：

*   **只读**此策略应用于永远不会更新的持久对象。 这对于读取和缓存应用配置以及其他静态数据非常有用。 这是具有最佳性能的最简单的策略，因为没有重载可以检查是否在数据库中更新了实体。
*   **读写**此策略对由应用更新的实体很有用。 但是，如果数据是通过数据库或其他应用更新的，则 Hibernate 无法判断是否发生了更改，并且您的数据可能已过时。
*   **非受限读写**如果应用仅偶尔更新数据并且不需要严格的事务隔离，则此缓存策略可能是合适的。
*   **事务性**此缓存策略为完全事务性缓存提供程序（例如 JBoss TreeCache）提供支持。 这样的缓存只能在 JTA 环境中使用，并且必须指定`transaction.manager_lookup_class`。

也不奇怪：EHCache 支持上述所有这四种策略，因此是开始使用二级缓存提供程序的不错选择。

## 查询缓存

另外，对于实体，您也可以将查询存储在缓存中。 但是，此查询缓存与二级缓存紧密配合，因此，如果您使用二级缓存，则这只是一种参加的方式。

要使用查询缓存，还需要两个额外的缓存区域：一个用于缓存的查询结果，另一个用于在最后更新表时的时间戳。

仅当您具有经常使用相同参数运行的**查询**时，才使用查询缓存。

## 结论

要对应用性能产生积极影响，第一步是在数据库和应用之间使用一些缓存。 Hibernate 提供了一个简单的内存缓存，称为*一级缓存*，由于它是强制性的，因此您无需启用或配置它。

但是，您可以使用*二级缓存*扩展此功能，该缓存可跨应用的会话缓存对象。 如果您使用的是二级缓存，则可以通过通常使用相同参数调用的缓存查询来扩展缓存实体。

