hibernate笔记(四)

目标:

一、hibernate查询

二、hibernate对连接池的支持

三、二级缓存

一、hibernate查询

1. 查询概述

1) Get/load主键查询

2) 对象导航查询

3) HQL查询,  Hibernate Query language                  hibernate 提供的面向对象的查询语言。

4) Criteria 查询,   完全面向对象的查询(Query By Criteria  ,QBC)

5) SQLQuery, 本地SQL查询

缺点:不能跨数据库平台: 如果改了数据库,sql语句有可能要改

使用场景: 对于复杂sql,hql实现不了的情况,可以使用本地sql查询。

HQL查询


public class App {

private static SessionFactory sf;

static {

sf = new Configuration()

.configure()

.addClass(Dept.class)

.addClass(Employee.class)   // 测试时候使用

.buildSessionFactory();

}

/*

* 1) Get/load主键查询

2) 对象导航查询

3) HQL查询,  Hibernate Query language  hibernate 提供的面向对象的查询语言。

4) Criteria 查询,   完全面向对象的查询(Query By Criteria  ,QBC)

5) SQLQuery, 本地SQL查询

*/

@Test

public void all() {

Session session = sf.openSession();

session.beginTransaction();

//1) 主键查询

// Dept dept =  (Dept) session.get(Dept.class, 12);

// Dept dept =  (Dept) session.load(Dept.class, 12);

//2) 对象导航查询

// Dept dept =  (Dept) session.get(Dept.class, 12);

// System.out.println(dept.getDeptName());

// System.out.println(dept.getEmps());

// 3) HQL查询

// 注意:使用hql查询的时候 auto-import="true" 要设置true,

//  如果是false,写hql的时候,要指定类的全名

// Query q = session.createQuery("from Dept");

// System.out.println(q.list());

// a. 查询全部列

// Query q = session.createQuery("from Dept");  //OK

// Query q = session.createQuery("select * from Dept");  //NOK, 错误,不支持*

// Query q = session.createQuery("select d from Dept d");  // OK

// System.out.println(q.list());

// b. 查询指定的列  【返回对象数据Object[] 】

// Query q = session.createQuery("select d.deptId,d.deptName from Dept d");

// System.out.println(q.list());

// c. 查询指定的列, 自动封装为对象  【必须要提供带参数构造器】

// Query q = session.createQuery("select new Dept(d.deptId,d.deptName) from Dept d");

// System.out.println(q.list());

// d. 条件查询: 一个条件/多个条件and or/between and/模糊查询

// 条件查询: 占位符

// Query q = session.createQuery("from Dept d where deptName=?");

// q.setString(0, "财务部");

// q.setParameter(0, "财务部");

// System.out.println(q.list());

// 条件查询: 命名参数

// Query q = session.createQuery("from Dept d where deptId=:myId or deptName=:name");

// q.setParameter("myId", 12);

// q.setParameter("name", "财务部");

// System.out.println(q.list());

// 范围

// Query q = session.createQuery("from Dept d where deptId 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());

// e. 聚合函数统计

// Query q = session.createQuery("select count(*) from Dept");

// Long num = (Long) q.uniqueResult();

// System.out.println(num);

// f. 分组查询

//-- 统计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();

}

// g. 连接查询

@Test

public void join() {

Session session = sf.openSession();

session.beginTransaction();

//1) 内连接   【映射已经配置好了关系,关联的时候,直接写对象的属性即可】

// Query q = session.createQuery("from Dept d inner join d.emps");

//2) 左外连接

// Query q = session.createQuery("from Dept d left join d.emps");

//3) 右外连接

Query q = session.createQuery("from Employee e right join e.dept");

q.list();

session.getTransaction().commit();

session.close();

}

// g. 连接查询 - 迫切连接

@Test

public void fetch() {

Session session = sf.openSession();

session.beginTransaction();

//1) 迫切内连接    【使用fetch, 会把右表的数据,填充到左表对象中!】

// Query q = session.createQuery("from Dept d inner join fetch d.emps");

// q.list();

//2) 迫切左外连接

Query q = session.createQuery("from Dept d left join fetch d.emps");

q.list();

session.getTransaction().commit();

session.close();

}

// HQL查询优化

@Test

public void hql_other() {

Session session = sf.openSession();

session.beginTransaction();

// HQL写死

// Query q = session.createQuery("from Dept d where deptId < 10 ");

// HQL 放到映射文件中

Query q = session.getNamedQuery("getAllDept");

q.setParameter(0, 10);

System.out.println(q.list());

session.getTransaction().commit();

session.close();

}

}

Criteria 查询


//4) Criteria 查询,

@Test

public void criteria() {

Session session = sf.openSession();

session.beginTransaction();

Criteria criteria = session.createCriteria(Employee.class);

// 构建条件

criteria.add(Restrictions.eq("empId", 12));

// criteria.add(Restrictions.idEq(12));  // 主键查询

System.out.println(criteria.list());

session.getTransaction().commit();

session.close();

}

SQLQuery, 本地SQL查询


// 5) SQLQuery, 本地SQL查询

// 不能跨数据库平台: 如果该了数据库,sql语句有肯能要改。

@Test

public void sql() {

Session session = sf.openSession();

session.beginTransaction();

SQLQuery q = session.createSQLQuery("SELECT * FROM t_Dept limit 5;")

.addEntity(Dept.class);  // 也可以自动封装

System.out.println(q.list());

session.getTransaction().commit();

session.close();

}

2. 分页查询

分页SQL:

先查询总记录数,再分页查询。


// 分页查询

@Test

public void all() {

Session session = sf.openSession();

session.beginTransaction();

Query q = session.createQuery("from Employee");

// 总记录数

ScrollableResults scroll = q.scroll();  // 得到滚动的结果集

scroll.last(); //  滚动到最后一行

int totalCount = scroll.getRowNumber() + 1;// 得到滚到的记录数,即总记录数

// 设置分页参数

q.setFirstResult(0);

q.setMaxResults(3);

// 查询

System.out.println(q.list());

System.out.println("总记录数:" + totalCount);

session.getTransaction().commit();

session.close();

}

二、hibernate对连接池的支持

连接池,

作用: 管理连接;提升连接的利用效率!

常用的连接池: C3P0连接池

 

Hibernate 自带的也有一个连接池,且对C3P0连接池也有支持!

 

Hbm 自带连接池:

只维护一个连接,比较简陋。

可以查看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.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>

三、二级缓存

Hibernate提供的缓存

有一级缓存、二级缓存。 目的是为了减少对数据库的访问次数,提升程序执行效率!

一级缓存:

基于Session的缓存,缓存内容只在当前session有效,session关闭,缓存内容失效!

特点:

作用范围较小! 缓存的事件短。

缓存效果不明显。

概述

二级缓存:

Hibernate提供了基于应用程序级别的缓存, 可以跨多个session,即不同的session都可以访问缓存数据。 这个换存也叫二级缓存。

Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!如果用户想用二级缓存,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影响代码。

如果用户觉得hibernate提供的框架框架不好用,自己可以换其他的缓存框架或自己实现缓存框架都可以。

使用二级缓存

查看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)测试

测试二级缓存!

缓存策略

<class-cache usage="read-only"/>     放入二级缓存的对象,只读;

<class-cache usage="nonstrict-read-write"/>  非严格的读写

<class-cache usage="read-write"/>    读写; 放入二级缓存的对象可以读、写;

<class-cache usage="transactional"/>   (基于事务的策略)

集合缓存

<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] -->

<collection-cache

usage="read-write" collection="cn.itcast.b_second_cache.Dept.emps"/>

查询缓存

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"/>


App  测试类


public class App {

private static SessionFactory sf;

static {

sf = new Configuration()

.configure()

.addClass(Dept.class)

.addClass(Employee.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();

}

}

四、项目中session的管理方式

Session的创建方式:


@Test

public void testSession() throws Exception {

//openSession:  创建Session, 每次都会创建一个新的session

Session session1 = sf.openSession();

Session session2 = sf.openSession();

System.out.println(session1 == session2);

session1.close();

session2.close();

//getCurrentSession 创建或者获取session

// 线程的方式创建session

// 一定要配置:<property name="hibernate.current_session_context_class">thread</property>

Session session3 = sf.getCurrentSession();// 创建session,绑定到线程

Session session4 = sf.getCurrentSession();// 从当前访问线程获取session

System.out.println(session3 == session4);

// 关闭 【以线程方式创建的session,可以不用关闭; 线程结束session自动关闭】

//session3.close();

//session4.close(); 报错,因为同一个session已经关闭了!

}

时间: 2024-10-12 20:55:58

hibernate笔记(四)的相关文章

学习hibernate笔记

以前学习java的时候,一开始就学习了hibernate,那时候总觉得ssh非常高大上,所以就急忙看了下相关视频.不过因为实际需要不高,所以后来一直没有使用上hibernate组件.现在一年过去了,也疯狂学习了java一段时间了,做过几个不大的项目,但是总算对java有些了解.现在参加了工作,公司使用的就是ssh,所以这两天又重新开始捣鼓hibernate.这次学习直接使用editplus,直接开发.看了官网的demo,发现英语也没有想象中那么困难.哈哈,把自己的学习记录下来吧.这里主要记录三个

Caliburn.Micro学习笔记(四)----IHandle&lt;T&gt;实现多语言功能

Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能 说一下IHandle<T>实现多语言功能 因为Caliburn.Micro是基于MvvM的UI与codebehind分离, binding可以是双向的所以我们想动态的实现多语言切换很是方便今天我做一个小demo给大家提供一个思路 先看一下效果 点击英文  变成英文状态点chinese就会变成中文                          源码的下载地址在文章的最下边 多语言用的是资源文件建

代码管理工具 --- git的学习笔记四《重新整理git(1)》

1.创建版本库 mkdir  创建目录 cd  地址,到该地址下 pwd 显示当前目录 1.创建目录 $ mkdir startGit $ cd startGit $ pwd 显示当前目录 或者cd到桌面,然后再创建目录 2.初始化版本库 $ git init 初始化仓库 提示信息:Initialized empty Git repository in /Users/xingzai/Desktop/startGit/.git/ 建立一个空的git仓库在/Users/xingzai/Desktop

Hibernate笔记①--myeclipse制动配置hibernate

Hibernate 是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命 意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任. Hibernate笔记①--myeclipse制动配置hibernate

Linux学习笔记四:Linux的文件搜索命令

1.文件搜索命令  which 语法:which [命令名称] 范例:$which ls  列出ls命令所在目录 [[email protected] ~]$ which ls alias ls='ls --color=auto' /bin/ls 另外一个命令:whereis [名称名称],也可以列出命令所在目录. [[email protected] ~]$ whereis ls ls: /bin/ls /usr/share/man/man1/ls.1.gz /usr/share/man/ma

小猪的数据结构学习笔记(四)

小猪的数据结构学习笔记(四) 线性表之静态链表 --转载请注明出处:coder-pig 本章引言: 在二,三中中我们分别学习了顺序表中的线性表与单链表,线性表有点类似于 我们前面所学的数组,而单链表使用的最多的是指针,这里问个简单的问题, 如果是在以前没有指针的话,前辈先人们怎么实现单链表呢?大家思考下! 没有指针,那么用什么来代替呢?前辈先人们非常机智,想出了使用下标+游标的方式 来实现单链表的效果!也就是今天要讲的--静态链表! 当然你也可以直接跳过本章,因为有了单链表就没有必要用静态链表了

R实战读书笔记四

第三章 图形入门 本章概要 1 创建和保存图形 2 定义符号.线.颜色和坐标轴 3 文本标注 4 掌控图形维数 5 多幅图合在一起 本章所介绍内容概括如下. 一图胜千字,人们从视觉层更易获取和理解信息. 图形工作 R具有非常强大的绘图功能,看下面代码. > attach(mtcars) > plot(wt, mpg) > abline(lm(mpg~wt)) > title("Regression of MPG on Weight") > detach(m

Swift学习笔记四:数组和字典

最近一个月都在专心做unity3d的斗地主游戏,从早到晚,最后总算是搞出来了,其中的心酸只有自己知道.最近才有功夫闲下来,还是学习学习之前的老本行--asp.net,现在用.net做项目流行MVC,而不是之前的三层,既然技术在更新,只能不断学习,以适应新的技术潮流! 创建MVC工程 1.打开Visual studio2012,新建MVC4工程 2.选择工程属性,创建MVC工程 3.生成工程的目录 App_Start:启动文件的配置信息,包括很重要的RouteConfig路由注册信息 Conten

老男孩培训视频听课笔记四(在51cto上听的)

实际操作:     1.创建一个目录 mkdir 语法:mkdir [-mp] [目录名称]            一般与配合cd tree pwd等命令来实现,整个操作     2.建议一个文件 利用touch命令来完成 语法:touch [path]/filename            批量创建文件:        for f in `seq 1000`;do touch $f.txt;done         创建文件的命令很多:vi echo> > cat等命令      3.文件