Hibernate入门(7):HQL查询

Hibernate5 同时被 2 个专栏收录
10 篇文章 0 订阅
使用 Hibernate 进行 CURD 操作时候,插入、更新、删除操作可以直接通过对持久化实体(PO)实例来进行,对于查询操作,Hibernate 提供了以下3种方式来进行:
  • HQL 查询;
  • Criteria 条件查询(hibernate 5.x 已经废弃);
  • SQL 查询;
以下示例代码中出现的 HibernateUtil 类是一个封装的Session管理类,详看: HibernateUtil


Hibernate HQL查询


HQL(Hibernate Query Language) 是Hibernate提供的一种面向对象的查询语言,语法类似于SQL;
SQL 的操作对象是数据表、列等数据库对象,HQL 的操作对象是类、实例、属性等;

HQL 的基本使用

HQL 查询依赖于 Query 类,每一个 Query 对应一个查询对象;
Query 类支持链式调用,常用的 API 如下:
QuerycreateQuery(String HQLString)根据 HQL 语句创建 Query 实例
QuerysetXX(String key,XX xx)hibernate 5.2 以前的方式传递参数方式:设置 HQL 语句中的参数 ,如 setInteger(String key,Integer value),setString(String key,String value)等
Query setParameter(String key,Object value)
setParameter(int position,Object val)
hibernate5.2 之后的传递参数的方式,具体用法见下面;
QuerysetFirstResults(int index)设置返回的结果集从第几条记录开始
QuerysetMaxResults(int maxNum)设置本次放回结果集的最大结果数目
Listlist()返回查询的结果列表,以 List<Object> 的方式,返回列表中的每一个 Object 对应一条查询结果记录,可能是一个PO持久化实体,也可能是一个包含所有返回属性的 Object[] 数组;

基本示例
其中实体 Users 的建模如下:
EntityUsers
Propertyint id
String name
Date createDate
String icon
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.List;

public class TestHQL {
    public static void main (String[] args) throws Exception{
        //创建session,开启事务
        Session session = HibernateUitl.currentSession();
        Transaction tran = session.beginTransaction();

        /*查询示例1: 直接查询整个实体 */
        String hqlStr = "select u from Users as u " +      //hql查询模板
                        "where u.icon = :iconType ";       
        List list  = session.createQuery(hqlStr)           //创建Query对象
                .setParameter("iconType","1")              //设置hql模板参数
                .list();                                   //获取结果
       
        for(Object element : list){   //遍历结果
            Users user = (Users)element;
            System.out.println(user.getName()+" "+user.getCreateDate());
        }

        /*查询示例2:查询实体中的部分属性 */
        String hqlStr2 = "select u.name ,u.icon from Users as u " +                    
                        "where u.createDate between :startDate and :endDate";
        List list2 = session.createQuery(hqlStr2)                                         
                    .setParameter("startDate",new SimpleDateFormat("yyyy-MM-dd").parse("2017-01-11"))     
                    .setParameter("endDate",new Date())
                    .list();
        for(Object element : list2){     //遍历结果
            Object[] objs = (Object[])element;
            System.out.println(objs[0]+" "+objs[1]);
        }
        
        //提交事务,关闭session
        tran.commit();
        HibernateUtil.closeSession();
    }
}


HQL语句模板和参数设置
HQL语句一般使用模板的方式编写,以提高灵活性,类似与 JDBC 中的PreparedStatement ,当然也可以直接填写参数;
HQL 模板的占位符 有2种方式,一种为 “:N” 占位符(N为参数变量),一种为“?”占位符
//方式1
String hqlStr = "select u from Users as u " +      
                        "where u.icon = :iconType ";     //:iconType 指明一个命名为“iconType”的参数
List list  = session.createQuery(hqlStr)           
            .setParameter("iconType","1")           // 设置模板中参数“iconType”的值为"1"
            .list();                                   
//方式2
String hqlStr2 = "select distinct u from Users as u " +
                "where u.icon = ? ";     //? 指明一个参数
List list2  = session.createQuery(hqlStr2)
             .setParameter(0,"1")     //设置模板中第1个参数的值为“1”;
             .list();
Query 返回结果列表
Query 返回的结果是 以 List<Object> 的方式返回,返回List中的每一个 Object 对应一条查询结果记录;
这个 Object 可以是一个PO持久化实体(在查询结果可以转化为某个PO持久化实体时),也可以是一个包含所有返回属性的 Object[] 数组,如以上基本示例中的2个示例;




HQL 的基本语法


HQL 语句的语法基本类似于SQL,大部分 SQL99 中的关键字可以通用于 HQL 语句,HQL支持以下语法:
这些语法和 SQL99 中是基本一样的;
Select [distinct] 实体实例/实体属性 
from 实体类 [as] 实体示例名(别名)
where 查询条件
order by 实体属性 [asc / desc]
group by 实体属性
having 分组条
示例
//查询User类实例中 age > 12 的实例,依据 icon 属性分组,每个分组以 age 升序排序,返回所有符合要求的实例
select u from User u
where u.age > 12
order by u.age asc
group by u.icon

//查询User实例中以 name 属性以 'A' 开头的实例,返回所有符合要求的实例的 name,id 属性
select u.name u.id from User u 
where u.name like "A%"

HQL 中的聚合函数

HQL 支持在选出的属性上使用聚合函数,这些函数和SQL中的完全相同,如: avg ,count,max,min,sum
示例:
//查询User实例中 age>12 的数量
select count(u) from User u
where u.age > 12

HQL 中的条件表达式

HQL where子句中支持 SQL 的所有运算符,同时也支持 EJB-QL 的运算符;
SQL 运算符数学运算符::+ - * / 等;
二进制运算符:= 、>、<、!= 、like 等;
逻辑运算符:and、or、not 等;
字符串连接符,函数:|| (如 str || str2),concat(str1,str2)
其他运算符:in、not in、between、is null 、is not null、is empty、is not empty、member of、not member of 等
时间操作函数:current_time()、current_date()、current_timestamp()、second()、minute()、hour()等
EJB-QL 运算符substring()、trim()、lower()、upper()、length()、locate()、abs()、sqrt()、bit_length()等

关联连接

HQL 支持两种方式的关联连接(join)方式:隐式(implict)、显式(explict);
在使用时优先推荐使用显式连接,隐式连接在 hibernate 3.2 之后 只能自动作用与普通的组件属性和1-1的关联实体,对于1-N、N-N的关联实体只能通过显式连接,隐式连接直接通过"."调用关联对象,底层会自动转化为 SQL99 的 交叉连接;
以下介绍显式连接:

1)关联连接类型:
  • inner join / join : 内连接
  • left join:左外连接
  • right join:右外链接
  • full join:全连接
※ 注意这些连接类型都会在底层转化为相应的SQL,前提条件是这些数据库要能支持这些关联连接操作;

2)关联连接基本语法
select 实体实例/实体属性 from 实体 [as] 实体实例(别名)
inner join 关联实体 [as] 关联实体实例(别名)
with 提供额外的关联连接条件,类似于SQL中的on
示例:
//User实体和Article实体之间的关联关系为 双向1-N,User中含有属性 Set<Article> atricles

//查找发布Article的数量>10 的 User 
Select u from User
inner join u.articles a
where count(a) > 10

//同上,同时连接时 User.id > Article.id
Select u from User
inner join u.articles a
with u.id > a.id
where count(a) > 10

3)解决关联实体延迟加载的问题
对于集合属性,hibernate 默认采用延迟加载的策略。比如User中含有一个集合属性 articles,当User被加载时,默认不加载 articles,当 User 所在的 Session 被关闭时,User的实例将无法访问其关联的 articles。为了解决这个问题,有两种方式:
① 在关联实体的注解标签中,设置属性  fetch=FetchType.EAGER
② 在相关的HQL中使用  fetch 关键字,如下:
select u from User u
inner join fetch u.articles
※ fetch 关键字无法与 Query. setMaxResults() ,Query.setFirstResults() 方法共用;
※ full join fetch ,right join fetch 没有任何意义;

子查询

HQL 提供的子查询语法类似于 SQL,类似如下:
//查询 User中age大于平均的实例
select oldUser from User oldUser
where oldUser.age > (Select avg(u.age) from User u)


HQL 命名查询


Hibernate 支持将 HQL 语句放置到持久化实体的注解中,通过这种方式能进一步提高程序的解耦;
命名查询使用 @NamedQuery 标签,可以将多个 @NamedQuery 放置到一个 @NamedQueries 中 ,示例使用如下:
User.java
@Entity
@Table(name="users")
@NamedQuery(name="query1",query="select u from Users u where icon = :iconType")

public class Users {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Column(name="user_id")
    private int id;

    @Column(name="create_date")
    @Temporal(TemporalType.DATE)
    private Date createDate;
   ......
}
Test.java
public class TestHQL {
    public static void main (String[] args) throws Exception{
        Session session = HibernateUtil.currentSession();
        Transaction tran = session.beginTransaction();

        List list = session.getNamedQuery("query1")   //调用命令查询
                .setParameter("iconType","3")
                .list();
        .....
    }
}


DML风格的批量更新/删除

HQL 语句除了可以用于查询外,也可以用与批量 update,insert,如下:
 public static void main(String[] args){
        Session session = HibernateUtil.currentSession();
        Transaction tran = session.beginTransaction();
        
     //更新数据
        String hqlUpdate = "update User u set u.point = u.point + :increasePoint";
        int updateCount = session.createQuery( hqlUpdate)
                .setParameter("increasePoint",12)
                .executeUpdate();

     //删除数据
        String hqlDelete = "delete from User where point < :lowesrPoint";
        int deletedCount = session.createQuery(hqlDelete)
                .executeUpdate();


        tran.commit();
        HibernateUtil.closeSession();
 }

















  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

Al_assad

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值