hibernate之HQL查询

一、HQL简介

HQL(Hibernate Query Language)是一种面向对象的查询语言,依赖于Query类,每个Query实例对应一个查询对象。查询步骤如下:

1)获取Hibernate Session对象

2)编写HQL语句

3)以HQL语句作为参数,调用session的createQuery()方法创建查询条件

4)如果HQL语句包含参数,则调用Query的setXxx()方法为参数赋值

5)调用Query对象的list()或uniqueResult()方法返回查询结果列表(持久化实体集)

二、HQL查询

1、from子句

        String hql = "from HQLTeacher";
        Query query = session.createQuery(hql);
        List<HQLTeacher> list = query.list();
        for(HQLTeacher t : list) System.out.println(t.getName());

from后面还可以出现多个持久化类,此时将产生一个笛卡尔积或跨表的连接

a、笛卡尔积

        String hql = "from HQLTeacher,HQLStudent";
            Query query = session.createQuery(hql);
            List list = query.list();
            int i = 0;
            for(Object t : list) {//此时t时长度为2的数组
                Object[] ob = (Object[]) t;
                HQLTeacher ht = (HQLTeacher) ob[0];
                HQLStudent hs = (HQLStudent) ob[1];
                System.out.println(++i + " : " + ht.getName() + " | " + hs.getName());//结果条数为teacher和student条数的积
            }

b、连接

        String hql = "from HQLTeacher as t,HQLStudent as s where t.id = s.hqlTeacher";//hqlTeacher为Teacher在Student中的关联,如果没有关联映射填写相应关联键的名称即可
            Query query = session.createQuery(hql);
            List list = query.list();
            int i = 0;
            for(Object t : list) {
                Object[] ob = (Object[]) t;
                HQLTeacher ht = (HQLTeacher) ob[0];
                HQLStudent hs = (HQLStudent) ob[1];
                System.out.println(++i + " : " + ht.getName() + " | " + hs.getName());
            }

在实际开发中用到跨表连接时,通常会选择使用隐式或显式连接,而不是在from后紧跟多个持久话类。

2、关联和连接(前提持久化类内部做了映射关联

HQL支持两种关联连接:隐式和显式

a、隐式(不使用join关键字,使用英文.来隐式连接关联实体)

        String hql = "from HQLStudent as s where s.hqlTeacher.name = :name";
            Query query = session.createQuery(hql);
            query.setString("name", "teacher 1");//此时只取得name为teacher 1的student列
            List<HQLStudent> list = query.list();
            for (HQLStudent s : list) {
                System.out.println(s.getName() + " | " + s.getHqlTeacher().getName());
            }

上述代码中用到了占位符(:name),HQL提供两种占位符方式:英文问号+索引形式(?N)和名字前面加冒号(:参数名)

b、显式

        String hql = "from HQLStudent as s inner join s.hqlTeacher";//显式关联的并不是对方的持久化类,而是对方持久化类在本类中的关联实体,并省去了sql语句中关联条件(on后面内容)
            Query query = session.createQuery(hql);
            List list = query.list();//同隐式关联不同,此时结果集中存储的为被查询持久化对象和关联持久化对象所组成的Object数组对象
            int i = 0;
            for(Object t : list) {
                Object[] ob = (Object[]) t;
                HQLStudent hs = (HQLStudent) ob[0];
                HQLTeacher ht = (HQLTeacher) ob[1];
                System.out.println(++i + " : " + ht.getName() + " | " + hs.getName());
            }

同sql关联一样,显式关联有四种,inner join(内连接)、left join(左连接)、right join(右lianjie)、full join(外连接)

3、select子句

select用于选择指定属性或直接选择某个实体

a、select后只有一项

        String hql = "select s.name from HQLStudent as s";
            Query query = session.createQuery(hql);
            List<String> list = query.list();//此时结果集是属性对应的集合
            int i = 0;
            for (String s : list) {
                System.out.println(++i + " : " + s);
            }

b、select后有多项 

        String hql = "select s.name,s.hqlTeacher.name from HQLStudent as s";
            Query query = session.createQuery(hql);
            List list = query.list();//此时的结果集的元素为选择项组成的数组
            int i = 0;
            for (Object ob : list) {
                Object[] ob1 = (Object[]) ob;
                System.out.println(++i + " : " + ob1[0] + " | " + ob1[1]);
            }

c、select也支持将选择出的属性存入一个List对象

        String hql = "select new list(s.name,s.hqlTeacher.name) from HQLStudent as s";//通过new list()实现
            Query query = session.createQuery(hql);
            List<List> list = query.list();
            int i = 0;
            for (List ob : list) {
                System.out.println(++i + " : " + ob.get(0) + " | " + ob.get(1));
            }

d、select也支持将选择出的属性直接封装成对象

        String hql = "select new entity.hql.StudentTeacher(s.name as studentName,s.hqlTeacher.name as teacherName) from HQLStudent as s";
            Query query = session.createQuery(hql);
            List<StudentTeacher> list = query.list();
            int i = 0;
            for (StudentTeacher st : list) {
                System.out.println(++i + " : " + st.getStudentName() + " | " + st.getTeacherName());
            }

此时需要注意StudentTeacher类需要连同包名写全、需要有与选择属性名称相同的属性、有与选择属性个数相同的构造方法,创建对象类如下

package entity.hql;//包名

public class StudentTeacher {
   //对应属性
private String studentName; private String teacherName; public StudentTeacher(String studentName, String teacherName) {//构造方法 this.studentName = studentName; this.teacherName = teacherName; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public String getTeacherName() { return teacherName; } public void setTeacherName(String teacherName) { this.teacherName = teacherName; } }

4、聚集函数

        String hql = "select count(*) from HQLStudent as s";
            Query query = session.createQuery(hql);
            System.out.println(query.uniqueResult());

HQL支持的聚集函数于SQL的完全相同,有avg、count、max、min、sum

此外,同SQL一样HQL也支持where子句、表达式、order by、group by、子查询,实现与sql基本相同,这里不再叙述。分页查询可用query.setFirstResult();query.setMaxResults()方法设定

附件给出测试所用持久化类及hibernate启动代码

@Entity
@Table(name = "hql_student")
public class HQLStudent {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @ManyToOne(targetEntity = HQLTeacher.class)
    @JoinColumn(name = "teacher_id", referencedColumnName = "id")
    private HQLTeacher hqlTeacher;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HQLTeacher getHqlTeacher() {
        return hqlTeacher;
    }

    public void setHqlTeacher(HQLTeacher hqlTeacher) {
        this.hqlTeacher = hqlTeacher;
    }
}
@Entity
@Table(name = "hql_teacher")
public class HQLTeacher {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @OneToMany(targetEntity = HQLStudent.class, mappedBy = "hqlTeacher")
    private Set<HQLStudent> hqlStudents = new HashSet<HQLStudent>();

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<HQLStudent> getHqlStudents() {
        return hqlStudents;
    }

    public void setHqlStudents(Set<HQLStudent> hqlStudents) {
        this.hqlStudents = hqlStudents;
    }
}
public class HQLTestController {
    public static void main(String[] args) {
        Configuration cf = new Configuration().configure();
        SessionFactory sf = cf.buildSessionFactory();
        Session session = sf.openSession();
        Transaction ts = session.beginTransaction();
        try {
            String hql = "select count(*) from HQLStudent as s";
            Query query = session.createQuery(hql);
            System.out.println(query.uniqueResult());
            ts.commit();
        } finally {
            session.close();
            sf.close();
        }
    }
}

代码下载:https://github.com/shaoyesun/hibernate_study.git 

原文地址:https://www.cnblogs.com/sunjf/p/hibernate_HQL.html