Hibernate的查询,二级缓存,连接池
Hibernate的查询,二级缓存,连接池
1.Hibernate查询数据
Hibernate中的查询方法有5中:
1.1.Get/Load主键查询
使用get或者load方法来查询,两者之间的区别在前面已经分析过了,这里用代码示例一下:
    //1.主键查询
    @Test
    public void all(){
        Session session = new Configuration().configure().buildSessionFactory().openSession();
        session.beginTransaction();
        //1.主键查询
         Dept dept= (Dept) session.get(Dept.class, 1);
         Dept dept1= (Dept) session.load(Dept.class, 1);
        session.getTransaction().commit();
        session.close();
    }
1.2.对象导航查询
    //2.对象导航查询
    @Test
    public void all(){
        Session session = new Configuration().configure().buildSessionFactory().openSession();
        session.beginTransaction();
        //2.对象导航查询
        Dept dept= (Dept) session.load(Dept.class, 1);
        System.out.println(dept.getDeptName());
        System.out.println(dept.getEmps());
        session.getTransaction().commit();
        session.close();
    }
1.3.HQL查询
HQL:Hibernate Query language,  hibernate提供的面向对象的查询语
根据sql语言的查询分类,HQL查询也大致可以分为一下几种:
1.查询全部列
2.查询指定列
3.查询指定的列并封装为对象
4.条件查询(一个条件/多个条件and or/范围查询between and/模糊查询)
5.聚合查询
6.分组查询
7.连接查询
前六种方式的查询方式代码示例为:
    //3.HQL查询
    @Test
    public void hql(){
        Session session = sf.openSession();
        session.beginTransaction();
        //注意:使用HQL查询的时候,auto-import="true"要设置为true
        //如果是false,写HQL的时候,要指定类的全名
        SQLQuery q = session.createSQLQuery("FROM Dept");
        System.out.println(q.list());
        //1.查询全部列
        Query q = session.createQuery("from a_query.Dept");
        Query q = session.createQuery("select * from  a_query.Dept");//错误,不支持*
        Query q = session.createQuery("select d from a_query.Dept  d");
        System.out.println(q.list());
        //2.查询指定的列
        //返回对象数据Object
        Query q = session.createQuery("select d.depId,d.deptName from a_query.Dept as d");
        System.out.println(q.list());//[[Ljava.lang.Object;@11cfad4]
        //3.查询指定的列封装为对象【必须要提供带参构造器】
        Query q = session.createQuery("select new a_query.Dept(d.depId,d.deptName) from a_query.Dept  d");
        System.out.println(q.list());
        //4.条件查询:一个条件/多个条件and or/between and/模糊查询
        //条件查询:占位符
        Query q = session.createQuery("from Dept d where deptNmae=?");
        q.setString(0,"财务部");//使用下面方式设置参数也可以、
        q.setParameter(0,"财务处")
        System.out.println(q.list());
        //条件查询:命名参数
        Query q = session.createQuery("from Dept d where depId=:myId and deptName=:name");
        q.setParameter("myId",121);
        q.setParameter("name","财务部");
        System.out.println(q.list());
        //范围between and
        Query q = session.createQuery("from Dept d where depId between ? and ?");
        q.setParameter(0,1);
        q.setParameter(1,20);
        System.out.println(q.list());
        //模糊
        Query q = session.createQuery("from Dept d where deptName like ?");
        q.setString(0,"%部%");
        System.out.println(q.list());
        //5.聚合函数统计
        Query q = session.createQuery("select count(*) from Dept");
        Long num = (Long) q.uniqueResult();//不再使用list()方法
        System.out.println(num);
        //6.分组查询
        //统计t_employee表中,每个部门的人数
        //数据库写法:SELECT dept_id,COUNT(*) FROM t_employee GROUP BY dept_id;
        // HQL写法
        Query q = session.createQuery("select e.dept,count(*) from Employee e group by e.dept ");
        System.out.println(q.list());
        session.getTransaction().commit();
        session.close();
    }
连接查询
连接查询主要分为内连接和左外连接或者右外连接。
先看需求:显示员工名称,薪水,部门
使用SQL来查询可以这样写:
内连接:
SELECT e.empName,e.salary,d.deptName FROM t_dept d,t_employee e WHERE d.depId=e.dept_id;
SELECT e.empName,e.salary,d.deptName FROM t_dept d INNER JOIN t_employee e ON d.depId = e.dept_id;
左外连接:
需求:显示部门,以及部门下的员工,如果部门下没有员工,用null
SELECT e.empName,e.salary,d.deptName FROM t_dept d LEFT JOIN t_employee e ON d.depId = e.dept_id;
始终显示right join后面表的数据
SELECT e.empName,e.salary,d.deptName FROM t_employee e  LEFT JOIN t_dept d ON d.depId = e.dept_id;
使用HQL查询为:
    //HQL查询的连接查询
    @Test
    public void join(){
        Session session = sf.openSession();
        session.beginTransaction();
        //1.内连接【映射已经配置好了关系,关联的时候,直接写对象的属性就可以了】
        Query q = session.createQuery("from a_query.Employee e inner join e.dept");
        //数组中第一个元素是Employee,第二个元素是dept
        List<Object[]> list = q.list();//可以遍历得到结果了
        System.out.println(q.list());
        //2.左外连接
        q = session.createQuery("from a_query.Dept d left join d.emps");
        System.out.println(q.list());
        //右外连接
        q = session.createQuery("from a_query.Employee e right join e.dept");
        System.out.println(q.list());
        //3.迫切连接【使用fetch,会把右表的数据,填充到左表对象中】
        //迫切内连接
        q = session.createQuery("from Dept d inner join fetch d.emps");
		q.list();
        //迫切外连接
        Query q = session.createQuery("from Dept d left join fetch d.emps");
        q.list();
        session.getTransaction().commit();
        session.close();
    }
HQL的优化操作
如果sql写在java代码中是写死的,这样的化维护起来特别困难,常用的做法是将HQL的sql语句放在java对应的映射文件各种,然后在java中直接调用。但是sql放在映射文件中需要注意转义的字符
映射文件:
	<!--存放sql语句-->
        <query name="getAllDept">
            from Dept d where depId=:myId or deptName=:name
        </query>
        <!--这里的sql需要转义的字符要转义-->
        <query name="getLitter">
            from Dept d where depId < ?
        </query>
        <!--批量转义的时候使用CDATA区域-->
        <query name="getLitter2">
            <![CDATA[
                from Dept d where depId < ?
            ]]>
        </query>
优化代码示例:
    //HQL查询优化
    @Test
    public void hql_other() {
        Session session = sf.openSession();
        session.beginTransaction();
        // HQL写在java代码中会把HQL写死,不易维护
        //Query q = session.createQuery("from Dept d where depId=:myId or deptName=:name");
        // 优化做法是将HQL查询语句放到映射文件中
        //一般都放在对应的映射文件中
        Query q = session.getNamedQuery("getAllDept");//从配置文件中读取sql
        q.setParameter("myId",12); //设置参数
        q.setParameter("name","财务部");
        System.out.println(q.list());
        session.getTransaction().commit();
        session.close();
    }
1.4.Criteria查询
Criteria是完全面向对象的查询:QBC,Query By Criteria
/**
 * QBC查询
 */
public class QbcTest {
    private static SessionFactory sf;
    static {
        sf = new Configuration().configure().buildSessionFactory();
    }
    @Test
    public void all(){
        Session session = sf.openSession();
        session.beginTransaction();
        Criteria criteria = session.createCriteria(Employee.class);//查询了所有的对象
        //添加查询条件,字段=值
//        criteria.add(Restrictions.eq("empId",1));
        //根据主键查询
        criteria.add(Restrictions.idEq(1));
        System.out.println(criteria.list());
        session.getTransaction().commit();
        session.close();
    }
}
1.5.SQLQuery,本地SQL查询
缺点:不能跨数据库平台,如果改了数据库,sql语句有可能需要改。
使用场景:对于复杂SQL,HQL实现不了的情况可以使用本地sql查询
    //5.SQLQuery, 本地SQL查询
    //不能跨数据库平台: 如果该了数据库,sql语句有肯能要改。
    @Test
    public void sql(){
        Session session = sf.openSession();
        session.beginTransaction();
        SQLQuery q = session.createSQLQuery("SELECT * FROM t_dept limit 1")//查询数结果
                .addEntity(Dept.class);//封装结果
        System.out.println(q.list());
        session.getTransaction().commit();
        session.close();
    }
1.6.Hibernate分页查询
数据库SQL分页的时候,是先查询总记录数,再分页查询。
Hibernate对这个功能有简化,更方便一些:
代码示例:
/**
 * 分页查询
 */
public class QbcTest {
    private static SessionFactory sf;
    static {
        sf = new Configuration().configure().buildSessionFactory();
    }
    // 分页查询
    @Test
    public void paginator() {
        Session session = sf.openSession();
        session.beginTransaction();
        //1.获取数据库表里面的数据
        Query q = session.createQuery("from Employee");
        // 2.从记录数
        ScrollableResults scroll = q.scroll();  // 得到滚动的结果集
        scroll.last();							//  滚动到最后一行
        int totalCount = scroll.getRowNumber() + 1;// 得到滚到的记录数,即总记录数
        // 3.设置分页参数
        q.setFirstResult(0);
        q.setMaxResults(3);
        // 4.查询
        System.out.println(q.list());
        System.out.println("总记录数:" + totalCount);
        session.getTransaction().commit();
        session.close();
    }
}
2.Hibernate对连接池的支持
连接池作用:管理连接,提升连接的利用效率!
常用的连接池有:C3P0连接池
Hibernate自带的也有一个连接池,且对c3p0连接池也有支持
Hibernate自带的连接池,只维护一个连接,比较简陋,可以查询Hibernate.properties文件查看连接池详细配置
#################################
### Hibernate Connection Pool ###
#################################
hibernate.connection.pool_size 1        【Hbm 自带连接池: 只有一个连接】
###########################
### C3P0 Connection Pool###		   【Hbm对C3P0连接池支持】
###########################
#hibernate.c3p0.max_size 2				最大连接数
#hibernate.c3p0.min_size 2				最小连接数
#hibernate.c3p0.timeout 5000           超时时间
#hibernate.c3p0.max_statements 100     最大执行的命令的个数
#hibernate.c3p0.idle_test_period 3000    空闲测试时间
#hibernate.c3p0.acquire_increment 2     连接不够用的时候, 每次增加的连接数
#hibernate.c3p0.validate false
【Hbm对C3P0连接池支持,  核心类】
 告诉hib使用的是哪一个连接池技术。
#hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider
Hibernate对c3p0连接池支持,用到的核心类
hibernate.connection.provider_class
即:org.hibernate.connection.C3P0ConnectionProvider
Hibernate中配置连接池的地方在Hibernate.cfg.xml 中配置,此处的配置不会对已经配置好的数据库连接有影响,所有直接下数据库连接下面写就可以了.
<!-- 【连接池配置】 -->
		<!-- 配置连接驱动管理类 -->
		<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
		<!-- 配置连接池参数信息 -->
		<property name="hibernate.c3p0.min_size">2</property>
		<property name="hibernate.c3p0.max_size">4</property>
		<property name="hibernate.c3p0.timeout">5000</property>
		<property name="hibernate.c3p0.max_statements">10</property>
		<property name="hibernate.c3p0.idle_test_period">30000</property>
		<property name="hibernate.c3p0.acquire_increment">2</property>
3.二级缓存
Hibernate提供的缓存有一级缓存,二级缓存.目的是为了减少对数据库的访问次数,提高程序执行效率.
对于一级缓存:
基于session的缓存,缓存内容只在当前session有效,session关闭,缓存内容失效!
特点是:作用范围小,缓存的时间短,缓存效果不明显.
1.二级缓存概述
Hibernate提供了基于应用程序级别的缓存,可以跨多个session,即不同的seesion都可以访问缓存数据,这个缓存也叫二级缓存.
Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!如果用户想用二级缓存,只需要在Hibernate.cfg.xml中配置即可;不想用,直接移除,不影响代码.
如果用户觉得Hibernate提供的框架不好用,自己可以换其他的缓存框架或自己实现缓存框架都可以
2.使用二级缓存
查看Hibernate.properties配置文件,二级缓存如何配置:
##########################
### Second-level Cache ###
##########################
#hibernate.cache.use_second_level_cache false【二级缓存默认不开启,需要手动开启】
#hibernate.cache.use_query_cache true      【开启查询缓存】
## choose a cache implementation		【二级缓存框架的实现】
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider 默认实现
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
二级缓存使用步骤:
1.开始二级缓存
2.指定缓存框架
3.指定哪些类加入二级缓存
4.测试
3.缓存策略
<class-cache usage="read-only"/>     放入二级缓存的对象,只读;
	<class-cache usage="nonstrict-read-write"/>  非严格的读写
	<class-cache usage="read-write"/>    读写; 放入二级缓存的对象可以读、写;
	<class-cache usage="transactional"/>   (基于事务的策略)
4.集合缓存
<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] -->
		<collection-cache
usage="read-write" collection="cn.itcast.b_second_cache.Dept.emps"/>
5.查询缓存
list()默认情况只会放入缓存,不会从一级缓存中取出.
使用查询缓存,可以让list()查询从二级缓存中取出
代码示例:
Hibernate.cfg.xml中配置二级缓存
<!-- 【二级缓存配置】 -->
		<!-- a.  开启二级缓存 -->
		<property name="hibernate.cache.use_second_level_cache">true</property>
		<!-- b. 指定使用哪一个缓存框架(默认提供的) -->
		<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
		<!-- 开启查询缓存 -->
		<property name="hibernate.cache.use_query_cache">true</property>
		<!-- c. 指定哪一些类,需要加入二级缓存 -->
		<class-cache usage="read-write" class="cn.itcast.b_second_cache.Dept"/>
		<class-cache usage="read-only" class="cn.itcast.b_second_cache.Employee"/>
		<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] -->
		<collection-cache usage="read-write" collection="cn.itcast.b_second_cache.Dept.emps"/>
测试类:
public class App {
	private static SessionFactory sf;
	static {
		sf = new Configuration()
			.configure()
			.addClass(Dept.class)
			.buildSessionFactory();
	}
	// 1. 测试二级缓存的使用
	// 没有/有用 二级缓存
	@Test
	public void testCache() {
		Session session1 = sf.openSession();
		session1.beginTransaction();
		// a. 查询一次
		Dept dept = (Dept) session1.get(Dept.class, 10);
		dept.getEmps().size();// 集合
		session1.getTransaction().commit();
		session1.close();
		System.out.println("------");
		// 第二个session
		Session session2 = sf.openSession();
		session2.beginTransaction();
		// a. 查询一次
		dept = (Dept) session2.get(Dept.class, 10);  // 二级缓存配置好; 这里不查询数据库
		dept.getEmps().size();
		session2.getTransaction().commit();
		session2.close();
	}
	@Test
	public void listCache() {
		Session session1 = sf.openSession();
		session1.beginTransaction();
		// HQL查询  【setCacheable  指定从二级缓存找,或者是放入二级缓存】
		Query q = session1.createQuery("from Dept").setCacheable(true);
		System.out.println(q.list());
		session1.getTransaction().commit();
		session1.close();
		Session session2 = sf.openSession();
		session2.beginTransaction();
		q = session2.createQuery("from Dept").setCacheable(true);
		System.out.println(q.list());  // 不查询数据库: 需要开启查询缓存
		session2.getTransaction().commit();
		session2.close();
	}
}
4.项目中session的管理方式
    //项目中session的管理方式
    @Test
    public void testSession() throws Exception{
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
        //openSession:创建Session,每次都会创建一个新的session
        Session session1 = sf.openSession();
        Session session2 = sf.openSession();
        System.out.println(session1==session2);//false
        session1.close();
        session2.close();
        //线程方式创建session
        // 一定要配置:<property name="hibernate.current_session_context_class">thread</property>
        //getCurrentSession()创建或者获取session
        Session session3 = sf.getCurrentSession();
        Session session4 = sf.getCurrentSession();
        System.out.println(session3==session4);//true
        //关闭:以线程方式创建的session,可以不用关闭,线程结束时session自动结束
//        session3.close();
//        session4.close();//报错,因为同一个session已经关闭
    }
												
											Hibernate的查询,二级缓存,连接池的更多相关文章
- Hibernate中 一 二级缓存及查询缓存(1)
		
最近趁有空学习了一下Hibernate的缓存,其包括一级缓存,二级缓存和查询缓存(有些是参照网络资源的): 一.一级缓存 一级缓存的生命周期和session的生命周期一致,当前sessioin ...
 - Hibernate-ORM:16.Hibernate中的二级缓存Ehcache的配置
		
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客讲述Hibernate中的二级缓存的配置,作者将使用的是ehcache缓存 一,目录 1.二级缓存的具 ...
 - Hibernate的一级二级缓存机制配置与测试
		
特别感谢http://www.cnblogs.com/xiaoluo501395377/p/3377604.html 在本篇随笔里将会分析一下hibernate的缓存机制,包括一级缓存(session ...
 - hibernate 5的二级缓存案例讲解
		
hibernate 5的二级缓存案例讲解 本帖最后由 鱼丸儿 于 2018-1-20 11:44 编辑 大家好,今天来记录讲解一下磕磕绊绊的hibernate5 的二级缓存配置,一条路摸到黑 那么在这 ...
 - 具体解释Hibernate中的二级缓存
		
1.前言 这篇博客再前几篇博客的基础上来解说一下.Hibernate中的二级缓存.二级缓存是属于SessionFactory级别的缓存机制. 第一级别的缓存是Session级别的缓存,是属于事务范围的 ...
 - Hibernate中 一 二级缓存及查询缓存(2)
		
缓存:缓存是什么,解决什么问题? 位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之为缓存Cache.缓存目的:让数据更接近于应用程序,协调速度不匹配,使访问速度更 ...
 - Redis缓存连接池管理
		
import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.util.Assert;import ...
 - Spring 整合 Hibernate 时启用二级缓存实例详解
		
写在前面: 1. 本例使用 Hibernate3 + Spring3: 2. 本例的查询使用了 HibernateTemplate: 1. 导入 ehcache-x.x.x.jar 包: 2. 在 a ...
 - Hibernate笔记④--一级二级缓存、N+1问题、saveorupdate、实例代码
		
一级缓存及二级缓存 一级缓存也是Session 缓存 一个链接用户的多次查询使用缓存 跨用户 则无缓存 hibernate自带的 get和load都会填充并利用一级缓存 二级缓 ...
 - Hibernate+EhCache配置二级缓存
		
步骤: 第一步:加入ehcache.jar 第二步: 在src目录下新建一个文件,名为:ehcache.xml 第三步:在hibernate配置文件的<session-factory>下配 ...
 
随机推荐
- H264中的MapUnits
			
1 MapUnits 在FMO(Flexible Macroblock ordering)时,从宏块到条带组的映射是以MapUnits为基本单位,MapUnits可能为宏块,也可能是上下两个宏块(见下 ...
 - HDU 1847 Good Luck in CET-4 Everybody! 博弈
			
题目思路: 写出SG函数(1表示先手胜,0表示先手负) 110110110110-- 发现n%3==0时,Cici胜 #include<stdio.h> #include<strin ...
 - LWP::UserAgent介绍1
			
require LWP::UserAgent; my $ua = LWP::UserAgent->new; ); $ua->env_proxy; my $response = $ua-&g ...
 - ubuntu 10.4非法关机后上不了网
			
用的好好的ubuntu 10.4,非法关机后居然上不了网,右上角的网络图标也不见了,还以为是网卡问题,进入xp,发现一切正常,心里不断地诅咒ubuntu,该死的ubuntu,我windows还天天非法 ...
 - angularjs的forEach使用
			
最近一直在写angularjs中的http后台数据交互,存在的问题就是数据传输中数据格式的问题,如何将传输过来的数据转化为自己需要的数据.当然如果你会一点后台语言的话,完全可以用在后台把数据转化为需要 ...
 - Arduino使用注意问题及编程相关
			
1.Arduino的概念 arduino是一款便捷灵活方便上手的开源电子原型平台,包含硬件(各种型号的arduino板)和软件(arduino IDE), 是一个基于开放原始码的软硬件平台,构建于开放 ...
 - PIE使用阴影后的背景透明方法
			
使用PIE后,会发现如果有设置 box-shadow 时,当前 class 样式中设置 opacity 或者背景渐变透明都会无效了,其实也是有办法解决的 css3-container { filter ...
 - Spring 创建 IOC 容器 ClassPathXmlApplicationContext 类
			
一.ClassPathXmlApplicationContext 类的作用 在 Java 环境中使用 Spring 时,需要用 new ClassPathXmlApplicationContext(c ...
 - [BZOJ2339][HNOI2011]卡农
			
[BZOJ2339][HNOI2011]卡农 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见"试题描述" 输出示例 见& ...
 - 第八十四节,css布局小技巧及font-awesome图标使用
			
css布局小技巧及font-awesome图标使用 图片鼠标放上去遮罩效果,显示文字 当鼠标放上去时 /*最外层div*/ .a{ width: 384px; height: 240px; backg ...