Hibernate - hibernate 有几种查询方式
总结
1.HQL (Hibernate Query Language)
- 语法类似sql
- 把sql语句的表名换成了类名,把字段名换成实体类中的属性
- 具有跨数据库的优点
2.QBC (Query By Criteria)
- 使用Session实例的createCriteria(XXX.class)方法创建Criteria对象;
- 使用工具类Restrictions的方法为Criteria对象设置查询条件,Order工具类的方法设置排序方式,Projections工具类的方法进行统计和分组;
- 使用Criteria对象的list()方法进行查询并返回结果。
3.SQL (Structured Query Language)
- 违背了hibernate的跨平台优点,不易维护,不面向对象。不推荐使用。
HQL示例
参考:https://www.cnblogs.com/jasonjson/p/12430917.html
查询所有,条件查询,排序查询,分页查询,统计查询,投影查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | import com.utils.HibernateUtils; import org.hibernate.Query; import org.hibernate.Transaction; import org.hibernate.classic.Session; import org.junit.Test; import java.util.List; public class CustomerTestDemo06 { /** * HQL查询 * 把sql语句的表明换成了类名。把字段名换成实体类中的属性 */ //查询所有 @Test public void test01(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); Query query=s.createQuery( "from Customer" ); List list = query.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } //按条件查询--1.占位符 @Test public void test02(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); Query query=s.createQuery( "from Customer where lovel = ? or name like ?" ); query.setString( 0 , "做县官" ); //占位符从0开始的 query.setString( 1 , "%刘%" ); List list = query.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } //按条件查询--2.给占位符取名字 @Test public void test03(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //给参数区名 :名 规范是(:属性) Query query=s.createQuery( "from Customer where lovel = :a or name like :name" ); // query.setString("a","做县官"); //占位符从0开始的 // query.setString("name","%刘%"); //setParameter()方法,此参数类型更灵活 query.setParameter( "a" , "做县官" ); query.setParameter( "name" , "%刘%" ); List list = query.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } //排序查询 @Test public void test04(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //order by 列明 desc Query query=s.createQuery( "from Customer order by id desc " ); List list = query.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } /** * 分页查询,hibernate提供高了两个方法: * setFirstResult(),设置开始查询记录索引 * setMaxResults(),设置每页查询条数 * */ @Test public void test05(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //order by 列明 desc Query query=s.createQuery( "from Customer order by id desc " ); query.setFirstResult( 3 ); query.setMaxResults( 3 ); List list = query.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } /** * 统计查询,使用聚合函数: *count sum avg max min */ @Test public void test06(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //order by 列明 desc Query query=s.createQuery( "select count(*) from Customer" ); /*List list = query.list(); for (Object o : list) { System.out.println(o); }*/ Object o = query.uniqueResult(); //当返回结果唯一的时候使用此方法 System.out.println(o); tx.commit(); } /** * 投影查询: * 查询结果只需要部分字段,不需要全部不,且希望返回的结果是封装类,而不是Object * 用法:用在HQL语句中new 一个对象,并给对象一个具体的带参的构造函数 */ @Test public void test07(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //order by 列明 desc Query query=s.createQuery( "select new com.bean.Customer(id,name) from Customer" ); List list = query.list(); for (Object o : list) { System.out.println(o); } tx.commit(); } } |
HBC示例
参考:https://www.cnblogs.com/jasonjson/p/12430917.html
- Criteria 基本查询,条件查询,排序查询,分页查询,统计(投影)查询,
- DetachedCriteria 离线查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | package com.bean; import com.utils.HibernateUtils; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.Transaction; import org.hibernate.classic.Session; import org.hibernate.criterion.*; import org.junit.Test; import java.util.List; public class CustomerTestDemo07 { /** * QBC查询 * 更加面向对象的查询方式,它把生成语句的过程全都融入到方法之中 * 效率比HQL查询慢 */ //基本查询 @Test public void test01(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //获取Criteria对象 Criteria criteria = s.createCriteria(Customer. class ); List list = criteria.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } //条件查询 @Test public void test02(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //获取Criteria对象 Criteria criteria = s.createCriteria(Customer. class ); //添加查询条件 criteria.add(Restrictions.eq( "lovel" , "做县官" )); criteria.add(Restrictions.like( "name" , "%张%" )); List list = criteria.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } //分页查询 @Test public void test03(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //获取Criteria对象 Criteria criteria = s.createCriteria(Customer. class ); //设置分页 criteria.setFirstResult( 0 ); //起始下标 criteria.setMaxResults( 2 ); //每页显示条数 List list = criteria.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } //排序查询 @Test public void test04(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //获取Criteria对象 Criteria criteria = s.createCriteria(Customer. class ); //添加查询条件 criteria.addOrder(Order.desc( "name" )); List list = criteria.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } //统计查询 //使用sql自带的聚合函数 @Test public void test05(){ Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //获取Criteria对象 Criteria criteria = s.createCriteria(Customer. class ); //添加查询条件 criteria.setProjection(Projections.count( "id" )); Object o = criteria.uniqueResult(); System.out.println(o); tx.commit(); } //离线查询 //先用离线对象将查询条件封装,再交给session @Test public void test06(){ //1.获取DetachedCriteria离线对象 DetachedCriteria dc=DetachedCriteria.forClass(Customer. class ); //2.封装查询条件 dc.add(Restrictions.eq( "lovel" , "做县官" )); dc.add(Restrictions.like( "name" , "%张%" )); //3.获取session对象,开始事务 Session s=HibernateUtils.getCurrnetSession(); Transaction tx = s.beginTransaction(); //4.将离线对象转成Criteria对象 //Session s1=HibernateUtils.getCurrnetSession(); Criteria criteria = dc.getExecutableCriteria(s); //5.执行查询 List list = criteria.list(); for (Object o : list) { System.out.println((Customer)o); } tx.commit(); } } |
SQL示例
1 2 3 4 5 6 7 | static List sql() { Session s = HibernateUtil.getSession(); Query q = s.createSQLQuery( "select * from user" ).addEntity(User. class ); List<User> rs = q.list(); s.close(); return rs; } |
为何有了Criteria,还需要DetachedCriteria?
参考:https://www.cnblogs.com/jinsheng1027/p/11327159.html
我的理解:
1 | 为了“解耦”,解除Criteria和session的依赖关系。 |
HQL与QBC的区别
参考:https://blog.csdn.net/liuchangjie0112/article/details/51567321
两者优缺点
比较方面 |
HQL检索方式 |
QBC检索方式 |
可读性 |
和SQL查询语言比较接近,比较容易读懂 |
QBC把查询语句肢解为一组Criterion实例。可读性差。 |
功能 |
功能最强大,支持各种各样的查询。 |
没有HQL的功能强大,例如不支持报表查询和子查询,而且对连接查询也做了很多限制。 |
查询语句形式 |
应用程序必须提供基于字符串形式的HQL查询语句。 |
QBC检索方式封装了基于字符串形式的查询语句,提供了更加面向对象的接口。 |
何时被解析 |
HQL查询语句只有在运行时才会被解析 |
OBC在编译时就能被编译,因此更加容易排错 |
可扩展性 |
不具有扩展性 |
允许用户扩展Criterion接口 |
对动态查询语句的支持 |
尽管支持生成动态查询语句,但是编程很麻烦 |
适合于生成动态查询语句 |
连接查询的支持
指定的连接查询类型 |
HQL语法 |
QBC语法 |
适用范围 |
内连接 |
inner join或者join |
Criteria.createAlias() |
适用于有关联关系的持久化类,并且在映射文件中对这种关联关系作了映射。 |
迫切内连接 |
inner join fetch或者join fetch |
不支持 |
|
隐式内连接 |
|
不支持 |
|
左外连接 |
left outer join或者left join |
不支持 |
|
迫切左外连接 |
left outer join fetch或者left join fetch |
FetchMode.EAGER |
|
右外连接 |
right outer join或者right join |
不支持 |
|
交叉连接 |
ClassA,ClassB |
不支持 |
适用于 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?