Hibernate使用原生SQL查询
Hibernate使用原生SQL查询
Hibernate提供了原生的SQL语句的查询,通过createSQLQuery(String)和createNativeQuery(String)
,createSQLQuery(String)
是Hibernate5.x之前的版本的,在Hibernate5.x和之后,都采用的是createNativeQuery(String)
,使用原生SQL虽然麻烦,但是一些复杂的查询明显可以使用原生SQL更加方便实现各种复杂的关联查询,这里主要记录一下原生SQL查询在开发中经常使用到的一些用法。主要参考了官方的文档:https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#sql
准备
使用的Hibenate版本为5.4的;这里使用的数据库是MySQL,测试的数据库时sakila数据库,数据库初始化脚本: https://download.csdn.net/download/strive_or_die/11928949 ,如果需要但是没有积分,也可以在评论区留下邮箱号,看到了会直接发送到邮箱。。
普通的查询
Hibernate会通过ResultSetMetadata来判断每个字段值的存放位置以及类型,返回一个Object[]类型的数组,其实这种结果集应用场景并不广,所以实际开发中使用起来也不方便。
//查询所有的列
List<Object[]> objList = session.createNativeQuery("select * from actor").list()
//查询指定的列
List<Object[]> list = session.createNativeQuery("select actor_id as actorId,first_name as firstName from actor").setFirstResult(0).setMaxResults(5).list();
查询结果转为Map
使用setResultTransformer转为Map,一般转为了Map比上面的方式要好很多了,可以通过一些反射进行转为对象。如下所示:
List<Map> mapList = session.createNativeQuery("select actor_id as actorId,first_name as firstName from actor").unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).setFirstResult(0).setMaxResults(5).list();
查询结果转为Bean对象
使用setResultTransformer
转为指定对象,如果会报Hibernate的类型和实体类的类型不匹配的错误,则需要使用addScalar
指定结果列的Hibernate类型,使得两者类型匹配;例如下例中,Hibernate查出来的actorId是Short
,而Entity中定义了为Integer
,执行则会报错,所以添加了addScalar("actorId",IntegerType.INSTANCE)
将Hibernate的类型修改为Integer
。
List<Actor> actors = session.createNativeQuery("select actor_id as actorId,first_name as firstName from actor").addScalar("actorId",IntegerType.INSTANCE).unwrap(NativeQueryImpl.class)//将查询结果列转为指定的对象,可以是实体类,也可以是非实体类例如VO和DTO.setResultTransformer(Transformers.aliasToBean(Actor.class)).setFirstResult(0).setMaxResults(5).list();
标量查询
标量查询主要用于指定查询语句返回哪些字段的值,例如下列的select * from actor
通过标量查询,进行指定结果列,这样就不会将所有结果列都查询出来,只查询我们需要的结果列。
List<Object[]> listB = session.createNativeQuery("select * from actor").addScalar("actor_id").addScalar("first_name").setFirstResult(0).setMaxResults(5).list();
转为实体对象
a.返回一个实体对象
这种通过addEntity
的查询方式,可以将结果查询转为指定的实体类,但是有个点需要特别注意,**如果使用了实体对象,那么在查询时要将实体对象中有的属性全部在SQL语句中查询出来,否则就会报错。**报的错误如:SQLException: Column 'actor_id' not found
List<Actor> actorList = session.createNativeQuery("select actor_id,first_name ,last_name,last_update from actor").addEntity("com.hibernate.learn.po.Actor").setFirstResult(0).setMaxResults(5).list();
b.返回多个实体对象
通过addEntity
指定别名和实体类,添加多个Entity,查询多个实体类结果。例如下列所示:
String multiEntitySQL = "select ac.*,fi.* from actor ac " +"inner join film_actor fa on ac.actor_id = fa.actor_id " +"inner join film fi on fi.film_id = fa.actor_id";
List<Object[]> multiList = session.createSQLQuery(multiEntitySQL).addEntity("ac",Actor.class).addEntity("fi", Film.class).setFirstResult(0).setMaxResults(5).list();
//多个实体,按照addEntity的顺序排列
for (Object[] multiEntity : multiList){System.out.println("actor :"+ ((Actor)multiEntity[0]));System.out.println("film :"+ ((Film)multiEntity[1]));
}
当使用连接查询查询多个对象时,可以通过addEntity("xxx", XXX.class)
方法来根据数据库表的别名来引入多个实体类,这时如果需要将查询出来的所有的对象分别存入实体类中,只需要在查询出来的对象上添加{}
号即可,此时就会自动分类,{}
这种方式主要用于返回多个实体对象,而且实体对象的列名可能存在相同的,那么就需要使用{}
,这样Hibernate就可以区分了。例如上面语句可以改为如下所示:
String multiEntitySQL = "select {ac.*},{fi.*} from actor ac " +"inner join film_actor fa on ac.actor_id = fa.actor_id " +"inner join film fi on fi.film_id = fa.actor_id";
List<Object[]> multiList = session.createSQLQuery(multiEntitySQL).addEntity("ac",Actor.class).addEntity("fi", Film.class).setFirstResult(0).setMaxResults(5).list();
//多个实体,按照addEntity的顺序排列
for (Object[] multiEntity : multiList){System.out.println("actor :"+ ((Actor)multiEntity[0]));System.out.println("film :"+ ((Film)multiEntity[1]));
}
总结
一般来说,Hibernate提供的原生SQL查询的方式,常用的就是这些了,很多使用我们使用的都是将查询结果转为实体对象,这个可以通过addEntity
方式实现,还有将连接查询的结果列转为VO或者DTO,这个可以通过setResultTransformer(Transformers.aliasToBean(XXX.class))
实现,对于查询结果为Object[]数组的是在是不方便处理。更多的实现可以参考Hibernate的官方文档:https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#sql
Hibernate使用原生SQL查询相关推荐
- hibernate的native sql查询
在我们的hibernate中,除了我们常用的HQL查询以外,还非常好的支持了原生的SQL查询,那么我们既然使用了hibernate,为什么不都采用hibernate推荐的HQL查询语句呢?这是因为HQ ...
- Hibernate原生SQL查询
最近在做一个较为复杂的查询,hibernate基本的查询不能满足,只好使用其提供的原生sql查询.参考网上的一些资料,做一些总结. 对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行 ...
- Hibernate使用原生SQL语句(left join左连接查询)
Hibernate使用原生SQL语句 以下是本人对Hibernate使用原生SQL语句的理解: 在项目开发当中使用Hibernate提供的HQL有时候不能满足需求,尤其是多表查询或者是多表中没创建主外 ...
- Hibernate5.2之原生SQL查询
原文:http://www.cnblogs.com/miller-zou/p/5720048.html 一. 介绍 在上一篇博客中笔者通过代码的形式给各位读者介绍了Hibernate中最重要的检索方 ...
- jpa 原生sql 查询返回一个实体_JPA查询--使用原生sql 并且把查询结果转为实体对象...
这篇文章主要记录 使用原生sql查询 并且把查询结果转为实体对象, 注意:这儿使用的数据库 是oracle数据库 这儿记录了三种查询:精确查询,模糊查询,分页查询. 1.把原生sql查询的结果转为实体 ...
- Hibernate对原生sql处理及结果集和VO的映射
昨天解决一个看似很简单的需求, 我有一个类似下面的table(info_table),是收集产品使用的机型信息: id type model 1 nokia xxx1 2 nokia xxx2 3 M ...
- 【Flask项目】sqlalchemy原生sql查询,返回字典形式数据
在原生sql查询的时候,返回一个list,内部是tuple,他们看似是tuple,实则并不是 而是一个特殊的类型"<class 'sqlalchemy.util._collection ...
- python graphql query返回一组字典数据_Python的sqlalchemy使用原生sql查询如何返回字典形式的数组?...
首先使用一个变量接收你以上的查询结果.这个查询结果是一个list,在这个list中包含着一个或多个tuple,其实这并不是标准的Python tuple,而是一个特殊的类型"",这 ...
- hibernate将本地SQL查询结果封装成对象
hibernate将本地SQL查询结果封装成对象 不知道大家有没有碰过这种情况,迫于很多情况只能用native SQL来查询(如:复杂统计等),然而使用native查询后,结果会被放到object里, ...
最新文章
- android 调用手机震动
- 连接远程数据库ORACLE11g,错误百出!
- 提升网站竞争力从这三方面着手努力!
- 【错误记录】编译 Android 版本的 ijkplayer 报错 ( You must define ANDROID_NDK before starting. | 下载指定版本 NDK )
- Linux 浏览网址汇集
- Y2011_M12_HeartChicken
- salt 文件push使用方法
- 一个JAVA WEB伪全栈的VUE入坑随笔,从零点零五学起
- Pytorch tensor基础知识
- JDK 运行参数 JAVA -Dxxx与System.setProperty()的关系
- “油猴脚本”获取百度云文件URL,百度云速度破解
- User Agreement(APP用户协议)
- 某云安全扫描对SQL Server潜入的观察日记
- 这款开源工具绝了!!!
- 高斯分布的性质(含代码)
- C++小实验之vector的 push_back 和 emplace_back 及其使用时机
- 微型计算机系统的发展历史,计算机的系统发展历史
- 中信国健临床通讯 2011年2月第1期
- 00 后程序员就要为“你”加班?呵呵
- 项目管理习题——挣钱分析法与成本预算和成本估算