Hibernate 二級緩存(L2 Cache)是 SessionFactory 級別 的緩存,跨會話共享。核心流程:
load()/get())優先檢查一級緩存 → 二級緩存 → 數據庫| ✅ 適合 | ❌ 不適合 |
|---|---|
| 極少修改(字典、配置、參考數據) | 頻繁修改的業務數據 | 允許極短暫臟讀(非核心財務) | 絕對一致性要求(財務、庫存扣減) | 非并發訪問或低并發 | 多應用共享數據庫(外部修改不可感知) |
ehcache-x.x.x.jar 放入 classpathhibernate-ehcache.jar;4.x/5.x 已內置<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 查詢緩存(可選) -->
<property name="hibernate.cache.use_query_cache">true</property>
<ehcache>
<diskStore path="java.io.tmpdir/ehcache"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!-- 實體緩存配置 -->
<cache name="com.example.domain.Category"
maxElementsInMemory="100"
eternal="true"
overflowToDisk="false"
/>
<!-- 集合緩存配置(格式:實體全限定名.屬性名) -->
<cache name="com.example.domain.Category.products"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="com.example.domain.Product"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
</ehcache>
<class name="Category" table="categories">
<cache usage="read-write"/> <!-- 實體緩存 -->
<id name="id" .../>
<version name="version" column="version"/> <!-- 必須有版本號支持樂觀鎖 -->
...
<set name="products" table="products" cascade="all" inverse="true">
<cache usage="read-write"/> <!-- 集合緩存 -->
<key column="categoryId"/>
<one-to-many class="Product"/>
</set>
</class>
<class name="Product" table="products">
<cache usage="read-write"/>
<id .../>
<version name="version"/>
...
</class>
| 策略 | 適用場景 | 事務隔離 |
|---|---|---|
read-only | 絕不修改(字典、配置) | 最快,無鎖 |
nonstrict-read-write | 極少修改,允許臟讀 | 適度性能 |
read-write | 常規讀寫,需一致性 | 軟鎖,性能較好 |
transactional | JTA 環境,強一致性 | 完全事務性,開銷大 |
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="hibernateProperties">
<props>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
</props>
</property>
</bean>
DAO 中啟用查詢緩存:
getHibernateTemplate().setCacheQueries(true);
List list = getHibernateTemplate().find("FROM Category");
<version> 支持樂觀鎖,否則并發更新會導致緩存不一致。<set>/<bag> 需單獨聲明 <cache>,且關聯實體也需配置緩存才能緩存完整對象(否則只緩存 ID)。executeUpdate())不會自動失效二級緩存,需手動 sessionFactory.getCache().evictEntityRegion()。Hibernate 二級緩存能顯著降低數據庫壓力,但配置復雜、易踩坑。核心原則:只緩存「讀多寫少、允許最終一致」的數據,嚴格配置版本號與並發策略,集群環境必選分布式緩存方案。建議配合監控(如 EhCache MBeans)觀察命中率,持續優化。