服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

hibernate和jive缓存策略的比较

一.基本概念

po是持久化对象,它只是对物理数据实体的一种对象表示。

vo是值对象,准确地讲,它是业务对象。

formbean只是html表单的封装,起到在控制层弱化的request中存储数据的作用,将request的get方法转

变为对象的存取值。

二.缓存策略比较

jive

1.jive的缓存策略的过程描述:

(1)条件查询的时候,jive用 select id from table_name where …. (只选择id字段)这样的sql语句查询数据库,来获得一个id列表。

(2) jive根据id列表中的每个id,首先查看缓存中是否存在对应id的数据对象:如果存在,那么直接取出,加入到 结果列表中;如果不存在,那么通过一条select * from table_name where id = {id value} 这样的sql查询数据库,取出对应的数据对象,放入到结果列表,并把这个数据对象按照id放入到缓存中。

(3) id查询的时候,jive执行类似第(2)步的过程,先从缓存中查找该id,查不到,再查询数据库,然后把结果放入到缓存。

(4) 删除、更新、增加数据的时候,同时更新缓存。

2.jive缓存策略的优点:

(1) id查询的时候,如果该id已经存在于缓存中,那么可以直接取出。节省了一条数据库查询。

(2) 当多次条件查询的结果集相交的情况下,交集里面的数据对象不用重复从数据库整个获取,直接从缓存中获取即可。比如,第一次查询的id列表为{1, 2},然后根据id列表的id从数据库中一个一个取出数据对象,结果集为{a(id = 1), b(id = 2)}。下一次查询的id列表为{2, 3},由于id = 2的数据对象已经存在于缓存中,那么只要从数据库中取出id = 3的数据对象即可。

3.jive缓存策略的缺点:

(1) 在根据条件查找数据对象列表的过程中,dao的第(1)步用来获得id列表的那一次数据库查询,是必不可少的。

(2) 如果第(1)步返回的id列表中有n个id,在最坏的命中率(缓存中一个对应id都没有)情况下,jive还要再查询n次数据库。最坏情况下,共需要n + 1数据库查询。

hibernate

hibernate用session类包装了数据库连接从打开到关闭的过程。session内部维护一个数据对象集合,包括了本session内选取的、操作的数据对象。这称为session内部缓存,是hibernate的第一级最快缓存,属于hibernate的既定行为,不需要进行配置。

session的生命期很短,存在于session内部的第一级最快缓存的生命期当然也很短,命中率自然也很低。当然,这个session内部缓存的主要作用是保持session内部数据状态同步。如果需要跨session的命中率较高的全局缓存,那么必须对hibernate进行二级缓存配置。一般来说,同样数据类型(class)的数据对象,共用一个二级缓存(或其中的同一块)。

hibernate

1.hibernate二级缓存策略的过程描述:

(1)条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的sql语句查询数据库,一次获得所有的数据对象。

(2) 把获得的所有数据对象根据id放入到第二级缓存中。

(3) 当hibernate根据id访问数据对象的时候,首先从session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照id放入到缓存。

(4) 删除、更新、增加数据的时候,同时更新缓存。

2.hibernate二级缓存策略的优点:

(1) 具有jive缓存策略同样的第(1)条优点:id查询的时候,如果该id已经存在于缓存中,那么可以直接取出。节省了一条数据库查询。

(2) 不具有jive缓存策略的第(2)条缺点,即hibernate不会有最坏情况下的 n + 1次数据库查询。

3.hibernate二级缓存策略的缺点:

(1) 同jive缓存策略的第(1)条缺点一样,条件查询的时候,第(1)步的数据库查询语句是不可少的。而且hibernate选择所有的字段,比只选择id字段花费的时间和空间都多。

(2) 不具备jive缓存策略的第(2)条优点。条件查询的时候,必须把数据库对象从数据库中整个取出,即使该数据库的id已经存在于缓存中。

hibernate的query缓存策略

可以看到,jive缓存和hibernate的二级缓存策略,都只是针对于id查询的缓存策略,对于条件查询则毫无作用。(尽管jive缓存的第(2)个优点,能够避免重复从数据库获取同一个id对应的数据对象,但select id from …这条数据库查询是每次条件查询都必不可少的)。

为此,hibernate提供了针对条件查询的query缓存。

1.hibernate的query缓存策略的过程描述:

(1) 条件查询的请求一般都包括如下信息:sql, sql需要的参数,记录范围(起始位置rowstart,最大记录个数maxrows),等。 

(2) hibernate首先根据这些信息组成一个query key,根据这个query key到query缓存中查找对应的结果列表。如果存在,那么返回这个结果列表;如果不存在,查询数据库,获取结果列表,把整个结果列表根据query key放入到query缓存中。

(3) query key中的sql涉及到一些表名,如果这些表的任何数据发生修改、删除、增加等操作,这些相关的query key都要从缓存中清空。

2.hibernate的query缓存策略的优点

(1) 条件查询的时候,如果query key已经存在于缓存,那么不需要再查询数据库。命中的情况下,一次数据库查询也不需要。

3.hibernate的query缓存策略的缺点

(1) 条件查询涉及到的表中,如果有任何一条记录增加、删除、或改变,那么缓存中所有和该表相关的query key都会失效。

比如,有这样几组query key,它们的sql里面都包括table1。

sql = select * from table1 where c1 = ? …., parameter = 1, rowstart = 11, maxrows = 20.

sql = select * from table1 where c1 = ? …., parameter = 1, rowstart = 21, maxrows = 20.

sql = select * from table1 where c1 = ? ….., parameter = 2, rowstart = 11, maxrows = 20.

sql = select * from table1 where c1 = ? ….., parameter = 2, rowstart = 11, maxrows = 20.

sql = select * from table1 where c2 = ? …., parameter = ‘abc’, rowstart = 11, maxrows = 20.

当table1的任何数据对象(任何字段)改变、增加、删除的时候,这些query key对应的结果集都不能保证没有发生变化。很难做到根据数据对象的改动精确判断哪些query key对应的结果集受到影响。最简单的实现方法,就是清空所有sql包含table1的query key。

(2) query缓存中,query key对应的是数据对象列表,假如不同的query key对应的数据对象列表有交集,那么,交集部分的数据对象就是重复存储的。

比如,query key 1对应的数据对象列表为{a(id = 1), b(id = 2)},query key 2对应的数据对象列表为{a(id = 1), c(id = 3)},这个a就在两个list同时存在了两份。

4.二级缓存和query缓存同步的困惑

假如,query缓存中,一个query key对应的结果列表为{a (id = 1) , b (id = 2), c (id = 3)}; 二级缓存里面有也id = 1对应的数据对象a。

这两个数据对象a之间是什么关系?能够保持状态同步吗?我阅读hibernate的相关源码,没有发现两个缓存之间的这种同步关系。或者两者之间毫无关系。就像我上面所说的,只要表数据发生变化,相关的query key都要被清空。所以不用考虑同步问题。

扫描关注微信公众号