在我们的hibernate中,除了我们常用的HQL查询以外,还非常好的支持了原生的SQL查询,那么我们既然使用了hibernate,为什么不都采用hibernate推荐的HQL查询语句呢?这是因为HQL查询语句虽然方便我们查询,但是基于HQL的查询会将查询出来的对象保存到hibernate的缓存当中,如果在我们的一个大型项目中(数据量超过了百万级),这个时候如果使用hibernate的HQL查询的话,会一次将我们查询的对象查询出来后放到缓存中,这个时候会影响我们的效率,所以当在大型项目中使用hibernate时我们的最佳实践就是--使用原生的SQL查询语句,而不使用HQL语句,因为通过SQL查询的话,是不会经过hibernate的缓存的。接下来我们就来看看hibernate的原生SQL查询

1.标量查询

在hibernate中,我们如果使用原生SQL查询的话,是通过SQLQuery接口进行的,我们首先来看看我们最基本的查询:

session.createSQLQuery("select * from t_student s").list()session.createSQLQuery("select ID,NAME,SEX from t_student s").list()

这就创建了最简单的两条SQL查询语句,此时返回的数据库表的字段值是保存在一个Object[]数组中的,数组中的每个元素就是查询出来的t_student表中的每个字段值,Hibernate会通过ResultSetMetadata来判断每个字段值的存放位置以及类型,接下来我们看下标量查询:

List<Object[]> stus = (List<Object[]>)session.createSQLQuery("select * from t_student s").addScalar("ID").addScalar("NAME").setFirstResult(0).setMaxResults(20).list();

这个查询语句指定了查询的字符串以及返回的字段和类型

这条查询语句仍然会返回一个Object[]类型的数组,但是此时就不会通过ResultSetMetadata,而是我们明确指定的ID,NAME,SEX,此时虽然查询语句中有 * 将所有的字段查询出来,但是这个时候仅仅只会返回我们指定的三个字段值,其类型还是由ResultSetMetada来指定的。

2.实体查询

①返回一个实体对象

上述的标量查询返回的裸数据,保存到了Object[]数组当中,我们如果要一个实体对象,将其保存到实体对象时就可以使用 addEntity()方法来实现:

@Testpublic void testSql1(){Session session = null;try{session = HibernateUtil.openSession();/** 原生的SQL语句查询,会将t_student表的所有字段查出来,存放的一个Object[]数组当中* 如果希望转换成实体对象,只需要调用 addEntity(Student.class)即可,这时,会首先匹配* Student对象里面的属性是否全部查询出来,如果没有,则报错(如果这个类是实体类)* 注意:如果要调用addEntity方法,这个类必须是实体类,即加了@Entity注解或者在XML中配置了实体类* 映射关系*/List<Student> stus = (List<Student>)session.createSQLQuery("select * from t_student s").addEntity(Student.class).setFirstResult(0).setMaxResults(20).list();for(Student stu : stus){System.out.println(stu.getName());}}catch (Exception e){e.printStackTrace();}finally{HibernateUtil.close(session);}}

这时我们就指定了将查询出来的对象存进Student这个实体类中,注意如果使用了实体对象,那么在查询时要将实体对象中有的属性全部在SQL语句中查询出来,否则就会报错

②返回多个实体对象

有的时候我们可能不只查询出一个实体对象,在使用连接查询时候,我们可能需要将几个表的数据都查询出来,并存放到对应的实体对象中去,这个时候我们应该怎么写呢?先看下如下一种写法:

List<Object[]> stus = (List<Object[]>)session.createSQLQuery("select stu.*, cla.*, spe.*"+ " from t_student stu left join t_classroom cla on stu.rid=cla.id"+ " left join t_special spe on spe.id=cla.sid where stu.name like ?").addEntity("stu", Student.class).addEntity("cla", Classroom.class).addEntity("spe", Special.class).setFirstResult(0).setMaxResults(20).setParameter(0, "%张%").list();

我们这里通过addEntity的一个重载方法给每个别名指定了一个关联的实体类,这个时候就会出现字段名冲突的问题,我们的本意是查询出三个实体对象,分别取得其name属性,但是name属性在这三张表中的字段都是name,这个时候查询出来的三个实体对象中的属性值都是一样的。我们如果要解决这个方法,只需要用一个 {} 花括号占位符将每个表的所有属性值括起来即可。如下:

@Testpublic void testSql3(){Session session = null;try{session = HibernateUtil.openSession();/*** 当使用连接查询查询多个对象时,可以通过addEntity("alias", XXX.class)方法来根据* 数据库表的别名来引入多个实体类,这时如果需要将查询出来的所有的对象分别存入实体类中,* 只需要在查询出来的对象上添加 {} 号即可,此时就会自动帮我们分类*/List<Object[]> stus = (List<Object[]>)session.createSQLQuery("select {stu.*}, {cla.*}, {spe.*}"+ " from t_student stu left join t_classroom cla on stu.rid=cla.id"+ " left join t_special spe on spe.id=cla.sid where stu.name like ?").addEntity("stu", Student.class).addEntity("cla", Classroom.class).addEntity("spe", Special.class).setFirstResult(0).setMaxResults(20).setParameter(0, "%张%").list();for(Object[] obj : stus){Student stu = (Student)obj[0];Classroom cla = (Classroom)obj[1];Special spe = (Special)obj[2];System.out.println(stu.getName() + ", " + cla.getName() + ", " + spe.getName());}}catch (Exception e){e.printStackTrace();}finally{HibernateUtil.close(session);}}

③返回不受hibernate管理的实体对象

我们有时候的需求是这样的,将每个表其中的一些字段查询出来,然后存放到一个javabean对象中,但是我们的这个bean对象又不需要存放到数据库,不需要设置成实体对象,这个时候我们往往会创建一个 DTO 的数据传输对象来存放我们要储存的属性,例如定义了一个 StudentDTO 对象:

public class StudentDTO
{private int sid;    // 学生idprivate String sname;  // 学生姓名private String sex;  // 学生性别private String cname;  // 班级名private String spename;  // 专业名public StudentDTO(){}public StudentDTO(int sid, String sname, String sex, String cname,String spename){super();this.sid = sid;this.sname = sname;this.sex = sex;this.cname = cname;this.spename = spename;}................
}

这个时候我们来看看我们的查询语句:

@Testpublic void testSql4(){Session session = null;try{    /*** 对于非Entity实体对象的类,我们如果要保持数据,可以通过定义一个DTO对象* 然后调用setResultTransformer(Transformers.aliasToBean(StudentDTO.class))方法* 来返回一个不受管的Bean对象*/session = HibernateUtil.openSession();List<StudentDTO> stus = (List<StudentDTO>)session.createSQLQuery("select "+ "stu.id as sid, stu.name as sname, stu.sex as sex, cla.name as cname, spe.name as spename"+ " from t_student stu left join t_classroom cla on stu.rid=cla.id"+ " left join t_special spe on spe.id=cla.sid where stu.name like ?").setResultTransformer(Transformers.aliasToBean(StudentDTO.class)).setFirstResult(0).setMaxResults(20).setParameter(0, "%张%").list();for(StudentDTO std : stus){System.out.println(std.getSname() + ", " + std.getCname() + ", " + std.getSpename());}}catch (Exception e){e.printStackTrace();}finally{HibernateUtil.close(session);}}

我们要将查询出来的这些不同的表的字段存放到一个不是实体对象当中,就可以调用 .setResultTransformer(Transformers.aliasToBean(StudentDTO.class)) 方法来创建一个非受管的 bean 对象,这个时候就hibernate就会将属性值存放到这个 bean 对象当中,注意查询出来的表的字段值存放到bean对象中,是通过调用 bean对象的 setter方法,如果该属性在bean对象中没有setter方法,则会报错

本篇是笔主在学习时记录一下如何来通过原生的SQL语句查询我们需要的信息,我们一定要记住,当数据量非常大的时候,强烈建议使用原生的SQL去查询数据,而不要使用HQL来查询,这样其实使用hibernate来说效率其实也不差,但是我们的增、删、改的操作则完全可以交给hibernate来完成。

转载于:https://www.cnblogs.com/xiuxun/p/7280835.html

hibernate使用sql进行查询相关推荐

  1. hibernate执行sql语句 查询 删除

    //执行删除sql语句 @Overridepublic void deleteById(String id) {// TODO Auto-generated method stubint a=this ...

  2. Hibernate:SQL查询 addScalar()或addEntity()

      Hibernate除了支持HQL查询外,还支持原生SQL查询. 对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取这个接口.该 ...

  3. hibernate 多条件组合查询之sql拼接

    hibernate 多条件组合查询之sql拼接 [java] view plaincopyprint? public static void main(String[] args) { Session ...

  4. Hibernate Native SQL查询示例

    Hibernate Native SQL查询示例 欢迎使用Hibernate Native SQL Query示例教程.我们在前面的文章中研究了Hibernate查询语言和Hibernate Crit ...

  5. 使用HIBERNATE的SQL查询并将结果集自动转换成POJO

    在某些场合下,我们可能想使用HIBERNATE的框架提供的SQL查询接口,但是,由于实体没有做映射,HIBERNATE不能把结果集转换成你想要的List<POJO>,本文讨论如何在这种情况 ...

  6. Hibernate 原生SQL多表查询时-字段名相同-查询数据覆盖问题

    问题描述 实际工作中通过Hibernate进行多表查询 两个实体类有相同属性 如下图所示 t_project_iter和t_project_story 表中TITLE 中字段名称相同 通过如下图方式进 ...

  7. hibernate mysql 关联查询_hibernate 查询缓存,以及在关联表查询缓存下使用HQL,而不是sql去查询...

    什么是查询缓存? 也就是如果开启了查询缓存, 在 没有使用二级缓存的情况下,会 缓存第一次查询出来的数据的id. 第二次查询的时候, 如果查询的参数和查询语句没有变化,那么就会使用 第一次查询的出来的 ...

  8. Spring Hibernate JPA 联表查询 复杂查询

    (转自:http://www.cnblogs.com/jiangxiaoyaoblog/p/5635152.html) 今天刷网,才发现: 1)如果想用hibernate注解,是不是一定会用到jpa的 ...

  9. Hibernate-ORM:14.Hibernate中的命名查询

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客讲述命名查询,所谓命名查询是什么呢? Hibernate中允许我们在xml,实体类,甚至注解的方式来编 ...

  10. Hibernate之HQL检索(查询)方式

    HQL(Hibernate Query Language)是面向对象的查询语言,与SQL非常相似.在Hibernate中,HQL是使用最广泛的检索方式. 具有下面经常使用功能: (1)在查询语句中,能 ...

最新文章

  1. Matplotlib绘制象限图——支持中文、箭头、自定义轴线交点
  2. redis-deskmanager 连不上 虚拟机 - centos redis
  3. JS详细入门教程(上)
  4. 大豆和黄豆芽还能吃吗?
  5. 研磨设计模式之 策略模式--转
  6. 1、用Anaconda配置Windows环境下的tensorflow(CPU版本)
  7. torch.tensor().permute(2,1,0)
  8. html css导航栏字体图标,HTML+CSS入门之两种图标字体库
  9. python-datetime模块190901
  10. 架构之重构的12条军规
  11. (转)HDOJ 4006 The kth great number(优先队列)
  12. python优化网站_小旋风网站优化 - 致力于Python高品质站群系统的产品研发
  13. JVM虚拟机第八章:堆
  14. win服务器系统无法切换输入法,Win10系统下中英文输入法无法切换的解决方案
  15. 下载离线地图数据(支持谷歌、百度、高德等所有地图源)
  16. 2021年物联网竞赛-A卷-ZigBee【CC2530】
  17. 35岁,转行AI年薪100万,牛逼的人生无需解释!
  18. 如何在表格里做计算机统计表,(excel怎么做统计表)excel表格如何制作数据表
  19. 剑指Offer题目详解(CPP、JAVA)
  20. OSChina 周五乱弹 —— 到底哪个更重要

热门文章

  1. List遍历的三种方式
  2. 操作系统导论 书中代码下载_经典教材统计学习导论终于有Python版了(附下载)...
  3. 有向无环图 前一个任务 后一个任务称为什么 英文
  4. Matlab关键规则挖掘尿片啤酒,电商数据挖掘之关联算法(一):“啤酒+尿布”的关联规则是怎么来的...
  5. cactiez mysql_cactiez v11添加对mysql数据库、apache系统进行监控
  6. Zookeeper 概述与安装、配置参数、数据结构、选举机制、客户端命令
  7. MongoDB 数据库_集合_文档 操作
  8. Trait这个类的特性
  9. JAVA Web基础3-Servlet
  10. 很感谢你能来,不遗憾你离开(好文章)