Hibernate---HQL查询

本文深入讲解Hibernate查询语言(HQL),涵盖其功能特性,如条件设定、投影查询、分页、连接查询等,并通过实例演示如何在Java环境中使用HQL进行数据库操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • Hibernate 提供了以下几种检索对象的方式
  1. 导航对象图检索方式: 根据已经加载的对象导航到其他对象
  2. OID 检索方式: 按照对象的 OID 来检索对象
  3. HQL 检索方式: 使用面向对象的 HQL 查询语言
  4. QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基>
    于字符串形式的查询语句, 提供了更加面向对象的查询接口.
  5. 本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句

HQL 检索方式

HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似. 在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式. 它有如下功能:

  1. 在查询语句中设定各种查询条件
  2. 支持投影查询, 即仅检索出对象的部分属性
  3. 支持分页查询
  4. 支持连接查询
  5. 支持分组查询, 允许使用 HAVING 和 GROUP BY 关键字
  6. 提供内置聚集函数, 如 sum(), min() 和 max()
  7. 支持子查询
  8. 支持动态绑定参数
  9. 能够调用 用户定义的 SQL 函数或标准的 SQL 函数

HQL 检索方式包括以下步骤:

  1. 通过 Session 的 createQuery() 方法创建一个 Query 对象, 它包括一个 HQL 查询. 语句. HQL 查询语句中可以包含命名参数
  2. 动态绑定参数
  3. 调用 Query 相关方法执行查询语句.
  • Qurey 接口支持方法链编程风格, 它的 setXxx() 方法返回自身实例, 而不是 void 类型

HQL vs SQL:

  • HQL 查询语句是面向对象的, Hibernate 负责解析 HQL 查询语句, 然后根据对象-关系映射文件中的映射信息, 把 HQL 查询语句翻译成相应的 SQL 语句. HQL 查询语句中的主体是域模型中的类及类的属性
  • SQL 查询语句是与关系数据库绑定在一起的. SQL 查询语句中的主体是数据库表及表的字段.
  • 示例:使用HQL查询数据库
  1. 使用Hibernate链接Oracle数据库
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>

        <property name="connection.username">scott</property>
        <property name="connection.password">tiger</property>
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="connection.url">jdbc:oracle:thin:@localhost:1521/mldn</property>


        <!--设置每次从数据库中读取的记录数量-->
        <property name="default_batch_fetch_size">100</property>

        <!--设置每次执行批处理的sql语句数量-->
        <property name="jdbc.batch_size">10</property>

        <!--配置数据库方言-->
        <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
        <!--是否打印sql语句-->
        <property name="show_sql">true</property>
        <!--是否对sql语句进行格式化-->
        <property name="format_sql">true</property>
        <!--指定自动生成数据表-->
        <property name="hbm2ddl.auto">update</property>
        <!--设置数据库的隔离级别-->
        <property name="connection.isolation">2</property>
        <!--改变delet()方法的行为-->
        <property name="use_identifier_rollback">true</property>
    </session-factory>
</hibernate-configuration>
  • 编写Employee程序类
public class Employee {
    private Integer id;
    private String name;
    private float salary;
    private String email;
    private Department dept;
    //getter和setter方法
}
  • 编写 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 package="mao.shu.vo" >

    <class name="Employee" table="GG_EMPLOYEE">
        <id name="id" type="java.lang.Integer">
            <column name="ID"/>
            <generator class="native"/>
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME"/>
        </property>
        <property name="email" type="java.lang.String">
            <column name="EMAIL"/>
        </property>
        <property name="salary" type="float">
            <column name="SALARY"/>
        </property>
        <many-to-one name="dept" class="Department">
            <column name="DEPT_ID"/>    
        </many-to-one>
    </class>
</hibernate-mapping>
  • 编写Department程序类
public class Department {
    private Integer id;
    private String name;

    private Set<Employee> emps = new HashSet<>();
    //getter和setter方法
}
  • 设置Department.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 package="mao.shu.vo" >

    <class name="Department" table="GG_DEPARTMENT">
        <id name="id" type="java.lang.Integer">
            <column name="ID"/>
            <generator class="native"/>
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME"/>
        </property>
        <set name="emps" table="GG_EMPLOYEE" inverse="true">
            <key>
                <column name="DEPT_ID"/>
            </key>
            <one-to-many class="Employee"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
  • 经这两个映射文件配置到Hibernate.cfg.xml文件之中
<mapping resource="mao/shu/vo/Department.hbm.xml"/>
<mapping resource="mao/shu/vo/Employee.hbm.xml"/>
  • 编写测试文件

public class DepartmentTest {
    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;

    @Before
    public void before(){
        Configuration configuration = new Configuration().configure();
        ServiceRegistry serviceRegistry =
                new ServiceRegistryBuilder()
                        .applySettings(configuration.getProperties())
                        .buildServiceRegistry();
        this.sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        this.session = this.sessionFactory.openSession();
        this.transaction = this.session.beginTransaction();
    }
    @After
    public void after(){
        this.transaction.commit();
        this.session.close();
        this.sessionFactory.close();
    }
    @Test
    public void test(){

        for (int i = 0; i < 10; i++) {
            Department department = new Department();
            department.setName("部门 = "+i);
            this.session.save(department);
            for (int j = 0; j < 10; j++) {
                Employee employee = new Employee();
                employee.setName("xiemaoshu"+i);
                employee.setSalary(100+i);
                employee.setEmail(i*100+10+i+"@"+i*100+10+i+".com");
                employee.setDept(department);
                this.session.save(employee);
            }
        }

    }

   @Test
    public void testHQL(){
        String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? AND e.dept = ?";
        Query query = this.session.createQuery(hql);
        Department dept = new Department();
        dept.setId(309);
        query.setFloat(0,100).setString(1,"%8%").setEntity(2,dept);
        List<Employee> emps = query.list();
       System.out.println(emps);
   }

}
  • 输出结果
  • 从测试中可以发现使用HQL查询语句中的占位符"?"即可以设置基本数据类型,也可以设置一个具体java对象
  • 并且每一个Query的"setXxx()"方法都会返回一个Query类对象,这就可以使用代码链的方式进行设置占位符

在这里插入图片描述

  • 在HQL语句之中还可以设置自定义的命名参数,参数在HQL语句中以":"开头
    @Test
    public void testHQLParameter(){
        String hql = "FROM Employee e WHERE e.email LIKE :email";
        Query query = this.session.createQuery(hql);
        query.setString("email","%8%");
        List<Employee> emps = query.list();
        System.out.println(emps);
    }

在这里插入图片描述

  • 在HQL语句之中还可以使用"ORDER BY"关键字来对查询结果进行排序
    @Test
    public void testHQLParameter(){
        String hql = "FROM Employee e WHERE e.email LIKE :email ORDER BY e.name";
        Query query = this.session.createQuery(hql);
        query.setString("email","%8%");
        List<Employee> emps = query.list();
        System.out.println(emps);
    }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值