Hibernate第四天——查询方式
Hibernate入门最后一天第四天,我们进行查询方式的更进一步的细化:
先看一下大致的Hibernate的提供的查询的方式:
1.对象导航查询
2.OID查询
3.HQL查询
4.QBC查询
5.本地SQL查询
使用框架,我们更加关注的是前四种查询的方式。
接下来逐条介绍:
1.对象导航查询
例如昨天的客户联系人的一对多:
根据id查询到客户,再根据客户下的所有联系人
这个查询过程称为对象导航
就是得到表示的那个set就可以
Set<LinkMan> set = cust.getSet_LinkMan();
/**
* 对象导航查询(顺便OID也在里面了)
* @author jiangbei01
*
*/
@Test
public void query1(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //查询客户中的所有联系人
Customer cust = session.get(Customer.class, 1);
//利用对象导航查询到所有联系人
//做法就是 得到那个表示所有联系人的set集合
Set<LinkMan> set = cust.getSet_LinkMan();
System.out.println(set.size());
//提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
2.OID查询
根据id查询某一条记录(返回的是对象)
也就是session.get方法实现
Customer cust = session.get(Customer.class, 1);
3.HQL查询
使用HQL语言(用到Query对象,昨天只演示了查询所有)==写语句
HQL与SQL最大的不同是:
HQL操作实体类
SQL操作表
HQL常用语句:
查询所有 === from 实体类名称
/**
* HQL Query对象查询所有
* @author jiangbei01
*
*/
@SuppressWarnings("deprecation")
@Test
public void query2(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery("from Customer");
//调用方法
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer.getCustLevel());
}
//提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
条件查询 === from 实体类名称 where 实体类属性=? ... 写法与SQL基本类似:
from 实体类名称 where 属性 like ?
/**
* HQL条件查询 第一步都是创建query对象
* 模糊查询极其类似,不再赘述举例这里 参数为String类型的即可(%浪%)
*/
@Test
public void query3(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery(
"from Customer c where c.cid=?");
//设置条件值,也就是向?设置值,一般都是用这个方法,而较少去使用其它重载方法
//第一个参数为int ?问号的位置,第二个为Object,这里必须注意:!!
//pstmt里面?从1 开始 ,这里从0开始!
query.setParameter(0, 1);
//调用方法
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer.getCustLevel());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
排序查询 === from 实体类名称 order by 属性 acs
/**
*演示排序
*/
@Test
public void query4(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery(
"from Customer order by cid asc");
//调用方法
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer.getCid());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
分页查询 === mysql中实现分页使用的是关键字 limit,注意此时hibernate不认识Limit这个方言!
/**
*演示分页
*/
@Test
public void query5(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery(
"from Customer");
//设置开始位置
query.setFirstResult(0);
//设置每页的记录数
query.setMaxResults(5); //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
使用的是query的封装的两个方法:
投影查询 === (用的不是很多,原因是查到所有后部分也简单)
投影的概念:查的是部分字段 例如 SELECT cid FROM t_stu
HQL与SQL这里也是极其相似
select 属性名1,属性名2 from 实体类名称(注意不能 写* ,写*查询所有应直接 from ...)
聚合函数 === 常用的COUNT() SUM() MAX/MIN() AVG()
HQL写法:
select count(*) from 实体类名称
使用这种接收只有某个的结果
Object o = query.uniqueResult();
注意此处返回值不能直接强转成int,因为此处o是long类型
应当先转成long类型,再转
Long不能直接强转,而是使用intValue()返回基本类型的值
/**
*演示聚合函数
*/
@Test
public void query6(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery(
"select count(*) from Customer");
//只返回某个值,而不用list
Object o = query.uniqueResult();
System.out.println(o); //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
}
4.QBC查询 (实际开发更倾向于此而少写HQL)
用到的是 Criteria对象 ==不写语句,这是与HQL不同的部分,而是使用方法操作实体类进行的操作
包含的也是这些:
查询所有:
得到对象,调用方法即可
/**
*演示QBC查询所有
*/
@Test
public void query6(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//调用方法实现
List<Customer> list = criteria.list();
//遍历结果集
for (Customer customer : list) {
System.out.println(customer.getCustName());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
条件查询:
通过方法控制条件
/**
*演示QBC条件查询
*/
@Test
public void query5(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//使用add()方法设置条件的值,更多请百度Restrictions静态类的用法
criteria.add(Restrictions.eq("cid", 1));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCustName());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
以下概念不再赘述,直接见案例
排序查询:
/**
*演示QBC排序查询
*/
@Test
public void query4(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//设置对哪个属性进行排序,包括排序方式和排序规则(似乎不如HQL方便)
criteria.addOrder(Order.desc("cid")); List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCustName());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
分页查询:
/**
*演示QBC分页查询
*/
@Test
public void query3(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//也是调方法,和HQL有点相似,设置分页的两个数据,注意:凡是设置的方法,一般都是先打set前缀
criteria.setFirstResult(0);
criteria.setMaxResults(2); List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCustName());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
统计查询:
, 统计记录条数等:
/**
*演示QBC统计查询
*/
@Test
public void query2(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//设置操作,其它操作举一反三
criteria.setProjection(Projections.rowCount());
//调用方法
Object o = criteria.uniqueResult();
Long l = (Long) o;
int r = l.intValue(); System.out.println(r); //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
离线查询:
步骤:
创建对象
设置操作
调用方法
离线查询:
之前的criteria是通过session查询的,是依赖session的
场景例子:希望在条件查询时就在servlet中实现条件的拼接
就是可以离线的操作
/**
*演示QBC离线查询
*/
@Test
public void query1(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建离线
DetachedCriteria detachedCriteria = DetachedCriteria
.forClass(Customer.class);
//最终执行的时候才用session
Criteria criteria = detachedCriteria.getExecutableCriteria(session); //再执行
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCustPhone());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
5.本地SQL查询
SQLQuery对象,使用本地SQL查询(前面有类似的案例,用的少的不再赘述)
当然,这里重点应该关注前4种查询方式
使用了上面的单表查询后,来看看HQL如何进行多表查询:
HQL多表查询(达到会用的水平先)
回顾mysql的一般多表查询:
内连接 INNER JOIN ON
左外连接 LEFT OUTER JOIN ON
右外连接 RIGHT OUTER JOIN ON
HQL实现多表查询:
1.内连接
2.左外连接
3.右外连接
4.迫切内连接
5.迫切左外连接(没有右外!勿擅自创造)
再次强调,HQL操作的是实体类,而不是表!
1.HQL内连接:
from Customer c inner join c.set_LinkMan
注意点:join后加的是表示联系人的set集合,并且后面没有on!
/**
*演示HQL内连接
*/
@Test
public void query1(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //HQL使用的是Query对象
Query query = session.createQuery("from Customer c inner join c.set_LinkMan");
List list = query.list();
//提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
2.迫切内连接和内连接的底层实现是一样的
迫切内连接返回的list每部分是对象
而内连接返回的list每部分是数组
from Customer c inner join fetch c.set_LinkMan
3.左外连接与迫切左外连接:
from Customer c left outer join c.set_LinkMan
from Customer c left outer join fetch c.set_LinkMan
同样的,左外连接返回的每部分是数组
迫切左外连接返回的是对象
迫切与普通连接查询的区别:
以上两种用法与1都相差无几。
Hibernate检索策略:
主要分为两类:
立即检索:
一调用get()方法马上发送SQL语句去查询
延迟检索:
调用load()方法,不会马上发送语句,
只有得到对象里面的值的时候,也就是什么时候用那个值
才发送语句,查询数据库,调用load()时,初始里面只有传入的id值
验证的方式是debug看发送语句的时机(F6一步一步走)
延迟查询中又分两类:(默认会有相关的延迟优化方式,自己修改的机会少)
类级别的延迟:
返回一个实体类的对象
在class标签上设置lazy值(选值见下)
关联级别的延迟:
查询某个客户,再查询客户里的所有联系人,
查询客户所有联系人的过程是否需要延迟
关联级别的延迟方式也可以自己修改(当然,默认的优化已经可以,作了解)
修改方式是在映射文件中进行配置
根据客户得到联系人,则配置客户的映射文件
在set标签上设置属性:
fetch:值select(默认)
lazy:值true 延迟(默认)
false 不延迟(遇到要用时都查出来给你)
extra 极其延迟(要什么给的什么,用size就只发送count(*))
/**
*演示立即查询与延迟查询
*/
@Test
public void query1(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//一调用get方法,马上去查询
Customer cust = session.get(Customer.class, 1);
System.out.println(cust.getCustName()); Customer cust1 = session.load(Customer.class, 2);//此时Customer中只有一个id值
System.out.println(cust1.getCustName());//去拿它的名字时才发语句去查询 //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
Hibernate的批量抓取(会用)
比如使用场景,需要查询所有客户(返回list)的联系人
可以先查出list,再逐个遍历(性能低)
这种对象导航仅仅实现了功能,却使得性能低下(发送了很多次的语句)
完成批量抓取的优化是通过映射文件的配置完成的
在set标签上配置属性 batch-size=""
这里面配置一个整形,没有固定值,值越大发的语句越少,性能越高(当然应当根据数据库记录数调优)
(可以查看底层SQL,使用的是in(?,?...)的形式,减少了语句的发送)
Hibernate第四天——查询方式的更多相关文章
- Hibernate的四种查询方式(主键查询,HQL查询,Criteria查询,本地sql查询)和修改和添加
Hibernate的添加,修改,查询(三种查询方式)的方法: 案例演示: 1:第一步,导包,老生常谈了都是,省略: 2:第二步,创建数据库和数据表,表结构如下所示: 3:第三步创建实体类User.ja ...
- hibernate的三种查询方式
hibernate的三种查询方式 目录 hibernate的三种查询方式 1.HQL查询 1.1.SQL概述 1.2.实体查询 1.3.带where的查询 1.3.属性查询 1.4.实体的更新和删除 ...
- hibernate学习笔记6--Criteria查询方式、完整小练习(开发步骤)
一.Criteria查询方式没有sql语了,因此更加面向对象一些.Criteria是一种比HQL更面向对象的查询方式:Criteria的创建方式: Criteria c = s.createCrite ...
- Hibernate之HQL检索(查询)方式
HQL(Hibernate Query Language)是面向对象的查询语言,与SQL非常相似.在Hibernate中,HQL是使用最广泛的检索方式. 具有下面经常使用功能: (1)在查询语句中,能 ...
- Hibernate的几种查询方式-HQL,QBC,QBE,离线查询,复合查询,分页查询
HQL查询方式 这一种我最常用,也是最喜欢用的,因为它写起来灵活直观,而且与所熟悉的SQL的语法差不太多.条件查询.分页查询.连接查询.嵌套查询,写起来与SQL语法基本一致,唯一不同的就是把表名换成了 ...
- sessionFactory的创建和四种查询方式
1,关于sessionFactory的创建 5.0版本之前,下面这种方式在5.0及之后,可能会出问题,建议修改为5.0之后的方式 // 实例化Configuration Configuration c ...
- Spring Data Jpa的四种查询方式
一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaR ...
- hibernate 查询方式汇总
主要摘自 http://blog.sina.com.cn/s/blog_7ffb8dd501014a6o.html ,http://blog.csdn.net/xingtianyiyun/artic ...
- Hibernate查询方式汇总
Hibernate总的来说共有三种查询方式:HQL.QBC和SQL三种.但是细分可以有如下几种: 一.HQL查询方式 这一种我最常用,也是最喜欢用的,因为它写起来灵活直观,而且与所熟悉的SQL的 ...
随机推荐
- kvm 启动libvirtd时出现错误
kvm 启动libvirtd市出现错误: /etc/init.d/libvirtd start启动 libvirtd 守护进程:libvirtd: relocation error: libvirtd ...
- idea 版本控制忽略文件、文件夹设置
setting 或者底部的 设置 忽略某个文件 后面选择框可以去选择 忽略某个文件夹 后面选择框可以去选择 忽略某种文件 后面输入填写如: *.txt
- C#关于微信昵称中存在的表情图标乱码解决
//在获取微信用户信息时加密保存到数据库 System.Web.HttpUtility.UrlEncode("需要加密的字段") //前端在展示是解码 <script typ ...
- 关于Nodejs开发桌面应用。NW.js 和 Electron 优缺点分析对比
从开发角度来说,选择用 nw.js 还是 election ,区别其实不是很大.大部分工作还是在自己的 javascript 和 HTML 上.国内比较有名的,比如微信web开发工具.钉钉都是基于 n ...
- 如何让chrome浏览器自动翻译
我用的chrome浏览器,最初用的时候浏览器默认自动翻译英文,我感觉很麻烦.所以我选择了一律不翻译.但是我当我想翻译的的时候又不知道怎么操作.一直郁闷到现在.今天我突然发现了一个方法可以让你的浏览器自 ...
- 渐变显示渐变消失的BackgroundView
渐变显示渐变消失的BackgroundView 效果如下: 源码: BackgroundView.h 与 BackgroundView.m // // BackgroundView.h // Test ...
- 程序员减少代码BUG的7种方法,拒绝编程5分钟,查代码2小时!
0.别对警告视而不见 相信不少的程序员会使用IDEA,使用它敲代码,有时候会出现警告,那么这时你对警告就不能视而不见了. 我们的目标是,写干净的代码,做风一样的男子! 1.编程习惯 种瓜得瓜种豆得豆, ...
- ZT 人生真的是一场马拉松吗?
中国合伙人:孟晓俊:生活应该是什么样的?自己提出的问题应该由自己来回答,别人的回答是别人的答案,是别人的生活,而你应该过自己的生活,不是别人的生活. 人生真的是一场马拉松吗? 投递人 itwr ...
- 《面向对象程序设计》 三 Calculator 计算器初步
Git传送门 纸上得来终觉浅,绝知此事要躬行. 学习了一些c++的相应知识后,虽然了解写法,真正操作时还是出现小错误.要多操作,记住关键点,避免不该有的小错误. 写分文件类外定义时出现了问题.在Sca ...
- 【译文】Web Service 众所周知的问题
1. 什么是web service Web Service是一种网络程序间的通信方式,它允许开发者用API方式暴露自己的业务逻辑功能,这样,其他开发者可以使用它 2. Web Service的特性 互 ...