Hibernate框架——二级缓存(二)

查询缓存

概念

  1. 查询缓存就是数据缓存,能够按照要求加载数据
  2. 一级缓存和二级缓存都是对象缓存,在表中的一行有多少个字段,就会加载多少个数据。

配置

  1. 建立在二级缓存基础之上的。
  2. 开启查询缓存
    1
    2
    <!-- 开启查询缓存-->
    <property name="cache.use_query_cache">true</property>

操作

案例一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void testQueryCache(){
Session session = HibernateUtils.sessionFactory.openSession();
Query query = session.createQuery("from Classes");
//允许把查询到的集合放入到查询缓存中。
query.setCacheable(true);
query.list();
session.close();
System.out.println("----------------");
session = HibernateUtils.sessionFactory.openSession();
query = session.createQuery("from Classes");
//允许从查询缓存中提取数据
query.setCacheable(true);
query.list();
session.close();
}

说明:
当执行第一个查询语句时,是会发出SQL语句的,当执行二个查询的时候,是不会发出SQL语句,因为利用查询缓存。 如下图:
查询缓存

案例二

当进行查询的SQL语句不同的时候,我们来看hibernate的查询缓存是否是会起作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void testQUeryCache2(){
Session session = HibernateUtils.sessionFactory.openSession();
Query query = session.createQuery("from Classes");
//允许把查询到的集合放入到查询缓存中
query.setCacheable(true);
query.list();
session.close();
System.out.println("---------------------");
session = HibernateUtils.sessionFactory.openSession();
query = session.createQuery("from Classes where cid = 1");
query.setCacheable(true);
query.list();
session.close();
}

hibernate执行SQL语句如下图所示:
SQL语句不同的时候查询缓存

说明:
1. 当两次query.lsit的时候,都会发出SQL语句
2. 原因是两次查询的hql语句不一样的,当发出的hql不一样的时候,就会重新发出SQL语句
3. 从这里可以看出查询缓存的命中率是比较低。

案例三

1
2
3
4
5
6
7
8
9
@Test
public void testQUeryCache3(){
Session session = HibernateUtils.sessionFactory.openSession();
Query query = session.createQuery("select name from Classes");
//允许把查询到的集合放入到查询缓存中
query.setCacheable(true);
query.list();
session.close();
}

上述代码中的query.list()的内存快照如下图:
query.list的内存快照

从list的内存快照中可以看出,list里存放的不是持久化对象,而是name属性的值。

一级缓存和二级缓存存放的是持久化对象,如果集合中存放的不是持久化对象,则不能进入二级缓存中,但是能够进入查询缓存中。

数据缓存和对象缓存

  1. 一级缓存和二级缓存是对象缓存,只能缓存持久化对象。
  2. 对象缓存的特点就是要把数据库表中所有的字段全部查询出来。
  3. 查询缓存是数据缓存,可以查询一个对象的部分属性,而且可以把部分属性放入到查询缓存中,查询缓存也支持对象。

Hql语句

单表

操作

以查询 Classes为例,下面就通过不同的hql语句进行分析,其中要注意的一点是:hql语句和SQL语句有相同的地方,也有不同的地方,比如在from xxx 表,SQL是查询表名字,但是hql 的from后面是接着类名字。

案例一

1
from Classes

查询的内存结构是如下图:
对象的hql
可以看到查询出来的elementData是一个Object类型的数组。

案例二

1
select cid, name, from Classes

查询后的list中内存结构如下图:
cid,name 的hql

说明:List中含有Object[], 该数组中有两个元素,第一个元素为Long类型,第二个元素为String类型。

案例三

1
select new com.wcc.hibernate.domain.Classes(cid, name) from Classes

new的hql

在持久化类中,必须有两个构造器

1
2
3
4
5
6
public Classes(){}
public Classes(Long cid, String name){
this.cid=cid;
this.name=name;
}

案例四:查询所有的数据个数

1
2
3
4
5
6
7
8
9
10
/**
* 查询classes表中所有的数据的个数
*/
@Test
public void testQueryCache5(){
Session session = HibernateUtils.sessionFactory.openSession();
Long count = (Long) session.createQuery("select count(*) from Classes").uniqueResult();
System.out.println(count);
session.close();
}

案例五:带参数的查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 带参数的查询 1
*/
@Test
public void testParameter(){
Session session = HibernateUtils.sessionFactory.openSession();
Query query = session.createQuery("from Classes where cid=?");
query.setString(0, "aa");
List<Classes> list = query.list();
System.out.println(list.size());
session.close();
}
/**
* 带参数的查询 2
*/
public void testParameter2(){
Session session = HibernateUtils.sessionFactory.openSession();
Query query = session.createQuery("from Classes where name:name");
query.setString("name", "aa");
List<Classes> classes = query.list();
System.out.println(classes.size());
session.close();
}

一对多

案例一

对Classes和Studentd持久化类进行查询,当查询语句如下的时候:

1
from Classes c, Student s where c.cid = s.classes.cid

根据上述的hql语句查询出的结果集的内存结构如下图所示:
等值连接查询内存结构图

案例二

对Classes和Student持久化类进行如下的hql语句进行查询:

1
form Classes c left join c.studnet s

查询结果的内存结构如下图:
进行左外连接内存结构
采用了左外连接,但是出来的结构不是很好。

案例三

1
from Classes c left outer join fetch c.studnets s

根据上述hql语句的查询语句进行查询,得到的内存结构如下次图:
使用fetch的查询语句内存结构图

说明:在join后面跟fetch,就为迫切左外连接。

案例四

1
from Classes c inner join fetch c.students s

根据上述的hql语句进行的查询后的结果的内存结构如下图:
inner jion 查询之后的内存结构图

案例五

1
select new com.wcc.hibernate.domain.ClassView(c.name, s.name) from Classes c iner join c.studnets s

根据上述的hql语句进行的查询结果的内存结构是如下图:
构造对象

说明:如果用select,则不能使用fetch,如果用fetch, 则不能使用select。

多对多

案例一

1
from Student s inner join fetch s.courses c

根据上面的hql语句进行的查询结果的内存结构如下图:
多对多的查询内存结构图

案例二

1
from Course c inner join fetch c.students s

根据上面的hql语句进行查询结果的内存结构如下:
多对多的查询内存结构如下图

坚持原创技术分享,您的支持将鼓励我继续创作!