HQL(Hibernate Query Language)使用详解


4.1基本查询HQL(Hibernate Query Language)

这是 Hibernate 官方所推荐的查询语言,接近 SQL 的语法,并提供更多的特性与封装。

使用HQL查询最简单的例子,就是查询指定类别对应表格的所有数据,例如:

Session session = sessionFactory.openSession();

Query query = session.createQuery("from User");

 

List names = query.list();

Iterator iterator =  names.iterator();

while(iterator.hasNext()) {

    User user = (User) iterator.next();

    System.out.println(user.getId() + "\t" +

                                      user.getAge() + "\t" +

                                      user.getName());

}

也可以指定类别的全名,例如:
Query query = session.createQuery("from onlyfun.caterpillar.User");
HQL本身不区分大小写,不过要注意类别的名称必须区分大小写。

在查询类别对应的表格时,需注意到继承的问题,Hibernate会自动判定继承关系,如果查询的类别是某类别的父类别,则会返回与父类别、子类别对应的所有表格数据,例如如果查询java.lang.Object,由于Object在Java中是所有类别的父类别,所以下面这个查询会返回数据库中所有表格的数据:
Query query = session.createQuery("from java.lang.Object");

如果要针对某个属性作查询,则可以如下:

Session session = sessionFactory.openSession();

Query query = session.createQuery("select user.name from User as user");

 

List names = query.list();

Iterator iterator =  names.iterator();

while(iterator.hasNext()) {

    System.out.println(iterator.next());

}

如果要查询两个以上的属性,则如下,查询的结果会以数组的方式传回:

Session session = sessionFactory.openSession();

Query query = session.createQuery("select user.age, user.name from User as user");

 

List names = query.list();

Iterator iterator =  names.iterator();

while(iterator.hasNext()) {

    Object[] obj = (Object[]) iterator.next();

    System.out.println(obj[0] + "\t" + obj[1]);

}

如果User类别提供有适当的建构方法,则可以在使用HQL时直接指定新建一个对象传回,例如若User如下设计:

package onlyfun.caterpillar;

public class User {

    private Integer id;

    private String name;

    private Integer age;

   

    public User() {

    }

   

    public User(String name, Integer age) {

        this.name = name;

        this.age = age;

    }

 

    ....

}

则在使用HQL查询时可以如下:

Session session = sessionFactory.openSession();

Query query = session.createQuery("select new User(user.name, user.age) from User as user");

 

List names = query.list();

Iterator iterator =  names.iterator();

while(iterator.hasNext()) {

    User user= (User) iterator.next();

    System.out.println(user.getAge() + "\t" + user.getName());

}

要注意的是,这个返回的User实例并未与数据库有任何关联,可以试着取得id属性,可以发现它的值是nul,如果试图使用Session的saveOrupdate()方法,则会新增一笔数据而不是更新原有的数据。

可以使用distinct去除数据重复的记录:

Query query = session.createQuery("select distinct user.age from User as user");

List names = query.list();

Iterator iterator =  names.iterator();

while(iterator.hasNext()) {

    System.out.println(iterator.next());

}

您也可以在HQL中使用函式,例如取得资料的笔数:

Query query = session.createQuery("select count(*) from User as user");

 

List names = query.list();

Iterator iterator =  names.iterator();

while(iterator.hasNext()) {

    System.out.println(iterator.next());

}

使用avg()取得属性的平均值:

Query query = session.createQuery("select avg(user.age) from User as user");

 

List names = query.list();

Iterator iterator =  names.iterator();

while(iterator.hasNext()) {

    System.out.println(iterator.next());

}

使用upper()函式将字符串转为大写:

Query query = session.createQuery("select upper(user.name) from User as user");

 

List names = query.list();

Iterator iterator =  names.iterator();

while(iterator.hasNext()) {

    System.out.println(iterator.next());

}

可以一并参考 Query 的使用。

4.2 where、group by、order by 子句
可以使用where子句来限定查询的条件,除了 = 运算之外,还有 >、>=、<、<=、!= 或 <>等比较运算,例如:

Session session = sessionFactory.openSession();

Query query = session.createQuery("from User user where user.name='caterpillar'");

 

List names = query.list();

Iterator iterator =  names.iterator();

while(iterator.hasNext()) {

    User user = (User) iterator.next();

    System.out.println(user.getAge() + "\t" + user.getName());

}

也可以在where子句上进行表达式,例如:
Query query = session.createQuery("from User user where (user.age / 10 = 3)");

也可以在where子句上使用and、or,例如:
Query query = session.createQuery("from User user where (user.age > 20) and (user.name = 'caterpillar')");

is not nullL与is null则可以测试字段值是否为空值,例如:
Query query = session.createQuery("from User user where user.name is not null");

between可以测试字段值是否在指定的范围之内,例如:
Query query = session.createQuery("from User user where user.age between 20 and 30");

可以使用in或not in来测试字段值是否在您指定的集合中,例如:
Query query = session.createQuery("from User user where user.name in('caterpillar', 'momor')");

like或not like可以让您进行模糊条件搜寻,例如想搜寻名称中含有cater开头的数据:
Query query = session.createQuery("from User user where user.name like 'cater%'");

可以对查询结果使用order by进行排序:
Query query = session.createQuery("from User user order by user.age");

可使用desc反排序:
Query query = session.createQuery("from User user order by user.age desc");

可同时指定两个以上的排序方式,例如先按照"age"反序排列,如果"age"相同,则按照"name"顺序排列:
Query query = session.createQuery("from User user order by user.age desc, user.name");

可以配合GROUP BY子句,自动将指定的字段依相同的内容群组,例如依字段"sex"分组并作平均:
Query query = session.createQuery("select user.sex, avg(user.age) from User user group by user.sex");

一个执行的结果如下:

+-------------------------------+

|    sex       |    avg(age)    |

+-------------------------------+

|    male      |    30          |

+-------------------------------+

|    female    |    25          |

+-------------------------------+

还可以结合having子句,例如只将平均大于20的数据分组显示出来:
Query query = session.createQuery("select user.sex, avg(user.age) from User user group by user.sex having avg(user.age) > 20");

 

4.3更新、删除
在Hibernate 2时,HQL只用于查询数据,要更新或删除数据,则是依赖于Session的update()、saveOrUpdate()、delete()等方法,在Hibernate 3中,HQL新增了update与delete语句,可以直接使用HQL指定更新或删除,例如使用update子句进行更新:

Session session = sessionFactory.openSession();

Transaction tx= session.beginTransaction();

Query query = session.createQuery("update User set name='momor' where name='bbb'");

query.executeUpdate();

tx.commit();

session.close();

使用delete子句进行数据删除:

Session session = sessionFactory.openSession();

Transaction tx= session.beginTransaction();

Query query = session.createQuery("delete User where name='bush'");

query.executeUpdate();

tx.commit();

session.close();

5.SQL 支援
Hibernate 提供了对 SQL 的支持,并可以自行定义持久化方式。

5、1建立 SQL 查询
Hibernate提供了对SQL的支持,您可以指定您所要建立的SQL,并将实体类别与数据表格关联,举个例子来说,如果您打算使用像以下的SQL语句:
SELECT * FROM user WHERE age > 20

则您可以如下建立SQL查询:

// SQL,并指定别名为user

String sql = "select {user.*} from User user where user.age > 20";

Session session = sessionFactory.openSession();

// 建立 SQLQuery

SQLQuery sqlQuery = session.createSQLQuery(sql);

// 将别名user与实体类User关联在一起

sqlQuery.addEntity("user", User.class);

Iterator iterator = sqlQuery.list().iterator();

while(iterator.hasNext()) {

    User user = (User) iterator.next();

    System.out.println(user.getAge() + "\t" + user.getName());

}

       

session.close();

addEntity()是将实体类别与别名连结在一起的方法,大括号指定要查询的数据,Hibernate根据所给定的SQL自动生成以下的句子:
select user.id as id0_, user.name as name0_0_, user.age as age0_0_ from User user where user.age > 20

返回的结果则由Hibernate进行封装为所指定别名关联之实体类,如此您可以得到使用SQL的弹性,但无需处理繁琐的ResultSet。

您也可以将SQL语句定义在映像文件中,例如:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping    

  PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    

  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

  <hibernate-mapping>

    <class name="onlyfun.caterpillar.User" table="user....   

    </class>

    <sql-query name="onlyfun.caterpillar.QueryUser">

      <![CDATA[           

        select {user.*} from User user where user.age > 20       

      ]]>       

      <return alias="user" class="onlyfun.caterpillar.User"/>

    </sql-query>

  </hibernate-mapping>

定义的时候,使用<return>卷标指定别名与实体类之关联,配合映像文件中的定义,您可以如下运行Hibernate:

Session session = sessionFactory.openSession();

Query query = session.getNamedQuery("onlyfun.caterpillar.QueryUser");

       

Iterator iterator = query.list().iterator();

while(iterator.hasNext()) {

    User user = (User) iterator.next();

    System.out.println(user.getAge() + "\t" + user.getName());

}

       

session.close();

也可以设定查询参数,例如:

....

<sql-query name="onlyfun.caterpillar.QueryUser">

<![CDATA[

select {user.*} from User user where user.age > :age

]]>

<return alias="user" class="onlyfun.caterpillar.User"/>

</sql-query>

....

使用Hibernate查询时如下:

Session session = sessionFactory.openSession();

Query query = session.getNamedQuery("onlyfun.caterpillar.QueryUser");

query.setInteger("age", 20);

 

Iterator iterator = query.list().iterator();

while(iterator.hasNext()) {

    User user = (User) iterator.next();

    System.out.println(user.getAge() + "\t" + user.getName());

}

       

session.close();

5.2自定义 insert、update、delete
Hibernate 3的映射文件中新增了<sql-insert>、<sql-update>与<sql-delete>三个标签,您可以在这三个标签中使用SQL自定义您的INSERT、UPDATE、DELETE,也就是储存、更新、删除数据时的行为,例如:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping    

  PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    

  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

  <hibernate-mapping>

    <class name="onlyfun.caterpillar.User" table="user">

      <id name="id" column="id" type="java.lang.Integer">

        <generator class="native"/>

      </id>

      <property name="name" column="name" type="java.lang.String"/>

      <property name="age" column="age" type="java.lang.Integer"/>

      <sql-insert>

        INSERT INTO user (name, age) VALUES (?, ?)       

      </sql-insert>

      <sql-update>

        UPDATE user SET name=?, age=?, WHERE id=?       

      </sql-update>

      <sql-delete>

        DELETE FROM user WHERE id=?       

      </sql-delete>

    </class>

  </hibernate-mapping>

? (参数) 对应的顺序是映像文件中属性出现的顺序,假设您储存对象:

session = sessionFactory.openSession();

tx = session.beginTransaction();

           

session.save(user);

tx.commit();

session.close();

则执行结果中显示的SQL语句会是您自定义的语句,而不是由Hibernate自动生成的语句:

Hibernate:

        INSERT INTO user (name, age) VALUES (?, ?)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值