Hibernate二级缓存
前言:
hibernate中的二级缓存是属于SessionFactory级别的缓存机制,一级别的缓存是Session级别的缓存,是属于事务范围的缓存,由Hibernate管理,一般无需进行干预。第二级别的缓存是SessionFactory级别的缓存,是属于进程范围的缓存。hibernate二级缓存中的缓存对象可以被整个应用的Session对象共享,即使关闭当前Session对象,新建的Session对象仍可使用。使用Hibernate的二级缓存之后查询数据,Session对象会首先在以及缓存中查找有无缓存数据被命中。如果没有,则查找二级缓存。如果有,则直接返回所命中的数据,否则查询数据库。所以hibernate的二级缓存是优化数据库的一个手段。
那么什么样的数据适合放在二级缓存中呢?
1.很少被修改的数据
2.不是很重要的数据
3不会被并发访问的数据
4常量数据
那么什么样的数据不适合放在二级缓存中呢?
1经常被修改的数据
2绝对不允许出现并发访问的数据。如财务数据,绝对不允许出现并发
3与其他应用共享的数据
1. 配置
1.1在hibernate.cfg.xml文件中:
<property name="hibernateProperties">
<props>
<!-- 配置二级缓存的所需的类 -->
<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</prop>
<!-- 配置启用查询缓存-->
<prop key="hibernate.cache.use_query_cache">
true
</prop>
<!-- 开启二级缓存 -->
<prop key="hibernate.cache.use_second_level_cache">
true
</prop>
<!-- 方言 -->
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQL5Dialect
</prop>
<!-- 是否开启显示sql发送 -->
<prop key="hibernate.show_sql">
true
</prop>
<!-- 是否自动创建|更新|验证数据库表结构 ,防止数据库表数据丢失建议为none-->
<prop key="hibernate.hbm2ddl.auto">
none
</prop>
</props>
</property>
1.2在src目录下建立一个文件,名字叫做encache.xml(必须叫这个名字),内容为:
<?xml version="1.0" encoding="UTF-8"?>
//防止加载不到encache文件,加上xmlns, xsi:noNamespaceSchemaLocation为所在路径
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
//当二级缓存对象超过我们设置的maxElementsInMemory数量时,才起作用么
<diskStore path="java.io.tmpdir" />
//全局配置
<defaultCache
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="1200"
overflowToDisk="true" />
//可对具体的类做具体的配置
<cache name="com.demo.hibernate.testDemo"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"/>
</ehcache>
2.针对具体类的配置
2.1以pojo类以注解的形式实现
@Entity
@Table(name="emp")
@Cacheable(value=true)
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public class Employee {
@Id
@Column(name="empno")
@GenericGenerator(name="assignedGenerator", strategy="assigned")
@GeneratedValue(generator="assignedGenerator")
private int id;
@Column(name="ename")
private String ename;
@Column(name="job")
private String job;
@Column(name="hiredate")
private Date hiredate;
@Column(name="sal")
private Double salary;
@Column(name="comm")
private Double comm;
//setter and getter(省略)
}
2.2在hibernate.cfg.xml文件中,采用<class-cache>标签
<class-cacheclass=" com.demo.hibernate.testDemo " usage="read-only"/>
注:
hibernate应用中,设置二级缓存的并发策略有两种方法,一种是通过Hibernate的全局配置文件,另一种是为各个Entity类单独设置。
1. 通过hibernate.cache.default_cache_concurrency_strategy配置参数,设置全局的二级缓存的并发策略
hibernate.cache.default_cache_concurrency_strategy配置参数的可用值:
read-only,适合只读事务
read-write,适合读写事务
nonstrict-read-write,适合高并发的读写事务
transactional,事务序列化
2. 使用Cache标注为各个Entity类单独设置二级缓存的并发策略,或者在<class-cache>标签中修改usage属性
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
3.测试
public class HibernateQBCTest {
private SessionFactory sf;
@Before
public void getSessionFactory(){
sf = OracleSessionUtils.getSessionFactory();
}
//查询所有
@Test
public void list(){
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
List<Employee> empList = session.createCriteria(Employee.class).list();
for(Employee e : empList){
System.out.println(e.getEname());
}
tx.commit();
session.close();
//以下查询不会发送SQL
Session session1 = sf.openSession();
Transaction tx1 = session1.beginTransaction();
Employee e = session1.get(Employee.class, 7369);
System.out.println(e.getEname());
tx1.commit();
session1.close();
}
}