一级缓存是session的缓存
二级缓存是sessionFactory的缓存
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 设置二级缓存插件EHCache的Provider类 -->
<property name="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<hibernate-mapping>
<class name="com.hibtest1.entity.User" table="user" catalog="bookshop">
<cache usage="read-only"/>
<id name="id" type="java.lang.Integer">
<column name="Id" />
<generator class="native" />
</id>
<property name="loginName" type="java.lang.String">
<column name="LoginName" length="50" />
</property>
</class>
</hibernate-mapping>
usage属性取值:
- read-only时表示只读型并发访问策略;
- read-write表示读写型并发访问策略;
- nonstrict-read-write表示非严格读写型并发访问策略
Hibernate查找对象如何应用缓存?
当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;
查不到,如果配置了二级缓存,那么从二级缓存中查;
如果都查不到,再查询数据库,把结果按照ID放入到缓存。
删除、更新、增加数据的时候,同时更新缓存
通过list()方法来获得对象,hibernate会发出一条sql语句,将所有的对象查询出来。
通过iterator()方法来获得我们对象的时候,hibernate首先会发出1条sql去查询出所有对象的 id 值,当我们如果需要查询到某个对象的具体信息的时候,hibernate此时会根据查询出来的 id 值再发sql语句去从数据库中查询对象的信息,这就是典型的 N+1 的问题
query.list()和query.iterator()方法的区别:
1.list每次都是通过一条语句直接操作数据库取出所有的数据返回(并且将对象存入hibernate缓存),在一个session中使用两次list()方法,都会发送查询语句,证明list()方法不使用缓存;
2.iterator首先通过一条语句取出所有数据的id,然后通过id在hibernate的一级缓存中查找是否存在该对象,如果存在则直接取出,如果没有则再次发出一条sql语句通过id取得对象(并且加入到缓存中),这样如果所有的id在缓存中都没有的话就会出现n+1条sql语句的问题。
3.所以两者需要合理的结合使用,最大提高性能。
4.使用list()后,数据在一级缓存中存在,再同一个session中使用iterator()的话,不会发送数据库语句,证明iterator()使用一级缓存,在一个session中使用两次list()方法,都会发送查询语句,证明list()方法不使用缓存