HQL实用技术

Hibernate查询

Hibernate支持3种查询方式,分别是HQL查询,Criteria查询,原生SQL查询

一.HQL查询

(一)什么是HQL

1.HQL:hibernate query language (Hibernate查询语言)
2. 语法和SQL很像,但是它是面向对象的查询语言,不是面向数据库
3. 除了Java类和属性的名称外,hql语句对大小写并不敏感
4. hql里面查询的是实体对象,所以写的是实体类的类名和属性名,严格区分大小写
5. HQL语句查询的是实体类的名称,不是数据库的表
6. HQL语句中的类名和属性名严格区分大小写

执行HQL语句的步骤
  1. 获取Session对象
  2. 编写HQL语句
  3. 创建Query对象
  4. 执行查询,得到查询结果

list()方法查询

//查询部门所有列表
public class App {
    public static void main(String[] args) {
//        1.读取hibernate.cfg.xml配置文件
        Configuration configuration = new Configuration().configure();
//        2.创建一个会话工厂
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        3.打开一个会话
        Session session = sessionFactory.openSession();
//        4.查询数据
        //定义HQL语句
        String hql = "from Department";  //查询的是类名称,不是表名
        //创建Query对象
        Query query = session.createQuery(hql);
        //执行查询,得到结果集
        List<Department> list = query.list();
        //循环遍历
        for (Department department : list) {
            System.out.println(department);
        }

//        5.关闭session
        session.close();
    }
}

iterate()方法查询

//查询部门所有列表
public class TestIterator {
    public static void main(String[] args) {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        //开启事务
        Transaction transaction = session.beginTransaction();
        //查询数据
        String hql = "from Department";
        Query query = session.createQuery(hql);
        //执行查询,得到结果集(会发出1+N条SQL语句)
        Iterator<Department> itor = query.iterate();
        while (itor.hasNext()) {
            //获取部门对象
            Department department = itor.next();
            System.out.println(department);
        }
        transaction.commit();
        session.close();
    }
}

list()方法和iterate()方法的区别:

  1. list()方法不会发出1+n条SQL语句 (list用的比较多)
  2. iterate()方法会发出1+n条SQL语句,在有缓存的基础上性能较好

HQL语句参数绑定

添加员工类Employee和员工映射文件
在这里插入图片描述
在resources下创建mapper包并在Employee.hbm.xml内配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!--
    class标签:用于关联实体类,通过name属性指定实体类
    name属性:关联实体类的路径
    table属性:实体类关联的表名称
    -->
    <class name="com.hbrj.dao.Employee" table="employee" >
        <!-- id标签配置主键字段-->
        <!-- name属性:填写该实体类的属性名称(严格区分大小写) -->
        <!-- column属性:填写数据库表中的列名称(不区分大小写),当列名与实体类的属性名相同时可以省
        略 -->
        <!-- type属性:填写该属性的数据类型 -->
        <id name="empNo" column="empNo" type="java.lang.Integer">
            <!-- 配置主键生成策略 -->
            <!-- assigned:主键由程序提供(非自增)-->
            <!--            <generator class="assigned"/>-->
            <generator class="increment"></generator>
        </id>
        <!-- property标签配置普通列名 -->
        <property name="empName" type="java.lang.String" column="empName"/>
        <property name="job" type="java.lang.String" column="job" />
        <property name="salary" type="java.lang.Double" column="salary"/>
        <property name="deptNo" type="java.lang.Integer" column="deptNo" />
        <property name="hireDate" type="java.util.Date" column="hireDate"/>
    </class>
</hibernate-mapping>

在hibernate.cfg.xml内加载映射文件在这里插入图片描述
在HQL语句中,给参数绑定数据可以使用以下2种方法,分别是:

  1. 按参数位置绑定
  2. 按参数名称绑定

高版本HQL参数绑定

  1. 观察HQL语句中的占位符?1,?2,其中?1是HQL语句中的第1个占位符
  2. 参数下标从1开始
/**
 * 查询某个部门下的员工信息
 */
public class QueryEmployee {
    public static void main(String[] args) {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        //查询数据,根据参数位置赋值,进行查询
        //定义HQL语句   HQL语句中的占位符?1,?2,其中?1是HQL语句中的第1个占位符
        String hql = "from Employee where deptNo=?1 and empName like ?2";
        Query query = session.createQuery(hql);
        query.setParameter(1, 1);
        query.setParameter(2, "%a%");
        List<Employee> list = query.list();
        for (Employee employee : list) {
            System.out.println(employee);
        }


        session.close();
    }
}

按参数名称绑定

HQL语句中可以使用 :参数名称 的方式进行传参,其中参数名称自定义

public class QueryEmployee2 {
    public static void main(String[] args) {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        //查询,根据参数名称进行复制             HQL语句中使用 :参数名称 的方式进行传参,其中参数名称自定义
        String hql = "from Employee where empName like :empName and salary >=:salary";
        Query query = session.createQuery(hql);
        query.setParameter("empName", "%a%");
        query.setParameter("salary", 6000.0);
        List<Employee> list = query.list();
        for (Employee employee : list) {
            System.out.println(employee);
        }

        session.close();
    }
}

Hibernate中的动态条件查询

  • setXXX(): 针对具体数据类型

    • setXXX(int position, XXX value)
    • setXXX(String name, XXX value)
  • setParamenter(): 任意类型参数

    • setParameter( int position, Object value)
    • setParameter( String name, Object value)
  • setProperties(): 专为命名参数定制

根据条件动态查询员工数据
1.根据职位查询,如:job=“Java工程师”
2.根据薪资查询,如:salary>=4000
3.入职时间 2018年1月1日 到 2020年1月1日
注意:条件个数不确定
说先自定义一个查询条件类(EmployeeVo)继承Employee
生成get和set方法
在这里插入图片描述

在hbrj下创建一个util包DateUtil类
用于转换时间日期

    public static Date parseDate(String str) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return format.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

开始写测试类

/**
 * 根据条件动态查询员工数据
 * 1.根据职位查询,如:job="Java工程师"
 * 2.根据薪资查询,如:salary>=4000
 * 3.入职时间 2018年1月1日 到 2020年1月1日
 */
public class QueryEmployee3 {
    public static void main(String[] args) {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        StringBuilder hql = new StringBuilder("from Employee where 1=1 ");
//动态条件查询
        //定义一个查询条件的类对象
        EmployeeVo employeeVo = new EmployeeVo();
        employeeVo.setJob("%员%");
        employeeVo.setSalary(5500.0);
        employeeVo.setStartDate(DateUtil.parseDate("2023-3-2 00:00:00"));
        employeeVo.setEndDate(DateUtil.parseDate("2023-3-9 00:00:00"));
        //EmployeeVo实体类中的成员变量名必须跟参数名称一致。
        if (employeeVo.getJob() != null) {  //判断职位
            hql.append("and job like :job "); //参数名称必须与实体类的属性名相同
        }
        if (employeeVo.getSalary() != null) {  //判断薪资
            hql.append("and salary >=:salary ");
        }
        if (employeeVo.getEmpName() != null) {  //判断名字
            hql.append("and empName like :empName ");
        }
        if (employeeVo.getStartDate() != null) {  //判断开始日期
            hql.append("and hireDate >=:startDate ");
        }
        if (employeeVo.getEndDate() != null) {  //判断结束日期
            hql.append("and hireDate <=:endDate");
        }
        Query query = session.createQuery(hql.toString());
        System.out.println(hql);
        //setProperties用来给参数赋值
        query.setProperties(employeeVo);
        List<Employee> list = query.list();
        for (Employee employee : list) {
            System.out.println(employee);
        }


        session.close();
    }
}

UniqueResult()唯一结果

uniqueResult()方法只能返回唯一结果,返回多行记录会报错

public class TestUniqueRestult {
    public static void main(String[] args) {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        //查询员工数量
        String hql = "from Employee where empNo=3";
        Query query = session.createQuery(hql);
        //uniqueResult必须保证查询结果只有一条记录    uniqueResult()方法只能返回唯一结果,返回多行记录会报错
        Object department = query.uniqueResult();
        System.out.println(department);
        session.close();
    }
}

分页查询

方法
uniqueResult() : 获取唯一对象
setFirstResult() : 设置从第几条开始
setMaxResults() : 设置读取最大记录数

public class QueryPage {
    public static void main(String[] args) {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        int pageSize = 3;//每页显示的条数
        int pageNo = 2;//从第几页开始
        String hql = "from Employee order by empNo asc";
        Query query = session.createQuery(hql);
        //设置分页信息
        query.setFirstResult((pageNo - 1) * pageSize);//从第几条开始,参数值为索引值
        query.setMaxResults(pageNo);//每页显示的条数
        List<Employee> list = query.list();
        for (Employee employee : list) {
            System.out.println(employee);
        }


        session.close();
    }
}

投影查询

投影查询是查询一个持久化类的一个或多个属性值,或者是通过表达式或聚合函数得到的值
投影查询需要使用HQL的select子句

查询结果的封装主要分三种情况

  1. 封装成Objec对象(返回单列)
  2. 封装成Object数组(返回多列)
  3. 通过构造方法封装成对象
封装成Objec对象------ 返回单列对象
//查询员工姓名
public class TestSelect {
    public static void main(String[] args) {
        //        1.读取hibernate.cfg.xml配置文件
        Configuration configuration = new Configuration().configure();
//        2.创建一个会话工厂
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        3.打开一个会话
        Session session = sessionFactory.openSession();
        String hql = "select empName from Employee";
        Query query = session.createQuery(hql);
        List<Object> list = query.list();
        for (Object employee : list) {
            System.out.println(employee);
        }


//        关闭session
        session.close();
    }
}
封装成Object数组----返回多列对象
//查询员工工号、姓名
ublic class TestObject {
    public static void main(String[] args) {
        //        1.读取hibernate.cfg.xml配置文件
        Configuration configuration = new Configuration().configure();
//        2.创建一个会话工厂
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        3.打开一个会话
        Session session = sessionFactory.openSession();

        //定义HQL语句
        String hql = "select empNo,empName from Employee";
        //创建Query对象
        Query query = session.createQuery(hql);
//        执行查询
        List<Object[]> list = query.list();
        for (Object[] employee : list) {
            System.out.println(employee[0] + "======" + employee[1]);
        }


//      关闭会话
        session.close();
    }
}
通过构造方法封装成对象

用构造方法实现投影查询,实体类中必须有一个与之对应的带参构造方法
在Employee实体类中生成如下带参构造方法:

public Employee(Integer empNo, String empName, String job) {
        this.empNo = empNo;
        this.empName = empName;
        this.job = job;
}

通过构造方法封装成对象
查询员工的 empNo,empName,job(工号,姓名,职位)

public class TestSelectConstructor {
    public static void main(String[] args) {
        //        1.读取hibernate.cfg.xml配置文件
        Configuration configuration = new Configuration().configure();
//        2.创建一个会话工厂
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        3.打开一个会话
        Session session = sessionFactory.openSession();

        //定义HQL语句
        //使用构造方法实现投影查询,实体类中必须有一个与之对应的带参构造方法
        String hql = "select new Employee(empNo,empName,job) from Employee";
        //创建Query对象
        Query query = session.createQuery(hql);
        //执行查询
        List<Employee> list = query.list();
        for (Employee employee : list) {
            System.out.println(employee);
        }
//        关闭会话
        session.close();
    }
}

原生SQL查询

以使用标准的SQL语句完成查询操作,同时可以使用数据库自带的函数,但条件参
数传递的方式要与HQL一致

注意

  1. 执行SQL语句的是SQLQuery接口中的createSQLQuery()方法
  2. 需要调用addEntity()方法将表与实体类关联
查询员工信息
public class TestSql {
    public static void main(String[] args) {
        //        1.读取hibernate.cfg.xml配置文件
        Configuration configuration = new Configuration().configure();
//        2.创建一个会话工厂
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        3.打开一个会话  (获取Session)
        Session session = sessionFactory.openSession();

        //定义SQL语句
        String sql = "select * from employee";
        //创建Query对象
        NativeQuery sqlQuery = session.createSQLQuery(sql).addEntity(Employee.class);
        //执行查询
        List<Employee> list = sqlQuery.list();
        for (Employee employee : list) {
            System.out.println(employee);
        }

//        关闭
        session.close();
    }
}
按条件查询
public class TestSql2 {
    public static void main(String[] args) {
        //        1.读取hibernate.cfg.xml配置文件
        Configuration configuration = new Configuration().configure();
//        2.创建一个会话工厂
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        3.打开一个会话
        Session session = sessionFactory.openSession();
        //定义SQL语句
        //String sql = "select * from employee where empName like ?1";
        String sql = "select * from employee where empName like :empName";
        //创建Query对象
        NativeQuery sqlQuery = session.createSQLQuery(sql).addEntity(Employee.class);
        sqlQuery.setParameter("empName", "%a%");
        //执行查询
        List<Employee> list = sqlQuery.list();
        for (Employee employee : list) {
            System.out.println(employee);
        }

//        关闭
        session.close();
    }
}

==================================================
mapper下Department.hbm.xml

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!--
    class标签:用于关联实体类,通过name属性指定实体类
    name属性:关联实体类的路径
    table属性:实体类关联的表名称
    -->
    <class name="com.hbrj.dao.Department" table="department">
        <!-- id标签配置主键字段-->
        <!-- name属性:填写该实体类的属性名称(严格区分大小写) -->
        <!-- column属性:填写数据库表中的列名称(不区分大小写),当列名与实体类的属性名相同时可以省
        略 -->
        <!-- type属性:填写该属性的数据类型 -->
        <id name="deptNo" column="deptNo" type="java.lang.Integer">
            <!-- 配置主键生成策略 -->
            <!-- assigned:主键由程序提供(非自增)-->
            <!--            <generator class="assigned"/>-->
            <generator class="increment"></generator>
        </id>
        <!-- property标签配置普通列名 -->
        <property name="deptName" type="java.lang.String" column="deptName"/>
        <property name="location" type="java.lang.String" column="location"/>
    </class>
</hibernate-mapping>

mapper下Employee.hbm.xml

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!--
    class标签:用于关联实体类,通过name属性指定实体类
    name属性:关联实体类的路径
    table属性:实体类关联的表名称
    -->
    <class name="com.hbrj.dao.Employee" table="employee" >
        <!-- id标签配置主键字段-->
        <!-- name属性:填写该实体类的属性名称(严格区分大小写) -->
        <!-- column属性:填写数据库表中的列名称(不区分大小写),当列名与实体类的属性名相同时可以省
        略 -->
        <!-- type属性:填写该属性的数据类型 -->
        <id name="empNo" column="empNo" type="java.lang.Integer">
            <!-- 配置主键生成策略 -->
            <!-- assigned:主键由程序提供(非自增)-->
            <!--            <generator class="assigned"/>-->
            <generator class="increment"></generator>
        </id>
        <!-- property标签配置普通列名 -->
        <property name="empName" type="java.lang.String" column="empName"/>
        <property name="job" type="java.lang.String" column="job" />
        <property name="salary" type="java.lang.Double" column="salary"/>
        <property name="deptNo" type="java.lang.Integer" column="deptNo" />
        <property name="hireDate" type="java.util.Date" column="hireDate"/>
    </class>
</hibernate-mapping>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值