Hibernate缓存机制详解

  Hibernate的一级缓存:

  Hibernate的一级缓存是一个线程对应一个Session,一个线程对应一个用户。也就是说Session级缓存只能给一个线程用,其它线程用不了。以及缓存和线程是绑定了的。Session间不能共享一级缓存。

  一级缓存也称Session级缓存或事务级缓存,如果事务提交或回滚了,那么Session就关闭了,生命周期结束

  Session与连接池的区别:池是重量级的,里面的数据都是一样的。缓存中的数据是不一样的。

  缓存主要用于查询。

  当使用get,load,iterate查询数据时,会进入一级缓存中查询。

  当一级缓存中没有数据时,get、iterate会发出sql语句,load会进入二级缓存。

  当使用iterate查询时,要注意,在没有缓存的情况下,会出现N + 1 的问题。

  iterate的N + 1问题:

  第一次iterate查询会发出N+1条sql语句,第一条sql语句查询所有的id,只有每个id发出sql语句查询实体

  第二次iterate查询时只发出一条查询所有id的sql语句,之后根据语句到缓存中查找实体对象。

  如果iterate查询的记过不是整个实体对象,java培训班而是对象中的某个属性,那么无论是第一次查询,

  还是第二次查询都会发出N+1条sql语句,因为一级缓存只缓存实体对象,不缓存普通属性。

  save()保存:

  经过save方法保存过的数据再进行查询时不会发出sql语句,因为save方法是支持缓存的。前提是同一个Session

  清理缓存:

  既然save方法支持缓存,那么问题就来了,如果进行了大批量的数据添加,例如执行了1000次save,

  则有可能会造成内存溢出的问题。所以我们就需要定量清理缓存中的内容。

  在清理缓存前,要先对缓存使用flush方法同步到数据库。

  Session级的缓存对性能的提高没有太大的意义,因为生命周期太短了。

  Hibernate二级缓存:

  二级缓存需要sessionFactory来管理,二级缓存是可以共享的。一般使用第三方产品实现。

  Hibernate自身也有,使用HashTable实现的,不过商用还是需要第三方产品。EHCache是个不错的选择。

  二级缓存的启用需要进行相应的配置,并不像一级缓存一样是默认开启的。

  必须手动指定哪些实体类的对象可以放到二级缓存中。

  当二级缓存开启过后

  如果使用两个不同的Session进行load查询,则第一次查询会发出sql语句,因为在

  缓存中没有数据,第二次不贵发出sql语句,因为第一次查询之后,在二级缓存中有了记录,并且二级缓存

  是可以共享的,所以会进入二级缓存查询数据。

  二级缓存也不会存放普通属性的查询数据,只存放对象实体。

  在进行大批量的数据添加时,如果出现内存溢出现象,不仅要清理以及缓存,还要清理二级缓存。

  我们查询的数据默认会放入一级缓存与二级缓存,前提是查询的对象允许放入二级缓存。

  Hibernate查询缓存:

  一级缓存与二级缓存都只能存放实体对象。如果查询实体对象的普通属性,只能放到查询缓存里面,

  查询缓存里面还存放了查询的实体对象的id。

  查询缓存的生命周期不确定,当它关联的表通过Hibernate修改过后,查询缓存的生命周期就结束了。

  查询缓存默认是关闭的,若要开启,需要在配置文件与程序中手动启用。

  对于查询缓存,Hibernate的list方法支持,当时iterate方法是不支持查询缓存的。

原文地址:https://www.cnblogs.com/gojava/p/3580268.html