Java进阶知识14 Hibernate查询语言(HQL),本文以hibernate注解版为例讲解

1、简单概述          

1.1、

1) SQL:面向的是数据库 select * from tableName;
2) HQL查询(Hibernate Query language): hibernate 提供的面向对象的查询语言。
    例:Session.createQuery(“from tableName”)  //和第1)点的SQL语句恒等的,查询出来的效果是一样的
3) Criteria 查询,完全面向对象的查询(Query By Criteria  ,QBC)
4) SQLQuery, 本地SQL查询,逻辑比较复杂,HQL很难实现

      缺点:不能跨数据库平台,如果改了数据库,sql语句有可能要改
      使用场景: 对于复杂sql,hql实现不了的情况,可以使用本地sql查询

HQL查询要注意:
      1、使用hql查询的时候 auto-import="true" 要设置true,如果是false,写hql的时候,要指定类的全名,例如:
           1.1、 Query q = session.createQuery("from Employee"); //auto-import="true"的时候
            1.2、Query q = session.createQuery("from com.shore.model.Employee"); //auto-import="false"的时候

       2、用注解版时,auto-import="true" (默认为true)写不写类的全名,都是可以的。用xml 配置版时,需要指定 auto-import="true" ,这样省代码,不指定为true,则像上面第1点的第1.2小点那样写。

1.2、查询全部列

1 Query query = session.createQuery("from Employee"); //OK
2 Query query = session.createQuery("from com.shore.model.Employee"); //OK
3 Query query = session.createQuery("select * from Employee"); //错误,不支持 *
4 Query query = session.createQuery("select e from Employee e"); // OK
5 System.out.println(query.list()); //把结果打印到控台上

1.3、查询指定的列

1 Query query = session.createQuery("select name,sex,salary from Employee");
2 System.out.println(query.list());

1.4、查询指定的列,自动封装为对象

1 Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary) from Employee");
2 System.out.println(query.list());

1.5、条件查询

  1.5.1、条件查询之占位符(?)

1 Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary) from Employee where department_id = ?");
2 //query.setParameter(0, 1);//或者下面的setInteger(0, 1)方法也行
3 query.setInteger(0, 1);
4 System.out.println(query.list());

  1.5.2、条件查询之命名参数(:

1 Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary) from Employee where department_id = :deptID");
2 query.setParameter("deptID", 1);
3 System.out.println(query.list());

  1.5.3、条件查询之范围查询(between .... and  ... )

1 Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary) from Employee where department_id between :d1 and :d2");
2 query.setParameter("d1", 1);   //也可以用占位符?实现
3 query.setParameter("d2", 2);
4 System.out.println(query.list());

  1.5.4、条件查询之模糊查询   like

1 Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary)  from Employee where name like ?");
2 query.setParameter(0, "%三%");
3 System.out.println(query.list());

1.6、聚合函数统计

1 Query query = session.createQuery("select count(*) from Employee where name like ?");
2 query.setParameter(0, "%三%");
3 System.out.println(query.list());

1.7、分组查询(group by

1 //MySQL数据库写法:select department_id,count(*) from employee group by department_id;
2
Query query = session.createQuery("select department,count(*) from Employee group by department_id"); //根据部门外键 3 System.out.println(query.list());

1.8、连接查询 (内连接、外连接、左/右连接等)

  内连接:Join == inner join  //交集
  左连接:Left join,以左边的表为主表,如果没有join上,左边表数据完整,右边表的数据可能为空 。//左边表的所有数据+右边表的交集部分
  右连接:Right join,以右边的表为主表,如果没有join上,右边表数据完整,左边表的数据可能为空。//右边表的所有数据+左边表的交集部分
  外连接:Outer join  //并集

 1 1) 内连接   【映射已经配置好了关系,关联的时候,直接写对象的属性即可】
 2 Query q = session.createQuery("from Employee e inner join e.department"); //department是Employee实体中映射的一个外键(Employee表中的department_id)
 3 
 4 2) 左外连接
 5 Query q = session.createQuery("from Employee e left join e.department");
 6 
 7 3) 右外连接
 8 Query q = session.createQuery("from Department d right join d.employee"); //映射的一个外键(employee_id)
 9 
10 4) 迫切内连接    【使用fetch, 会把右表的数据,填充到左表对象中!】
11 Query q = session.createQuery("from Employee e inner join fetch e.department");
12 q.list();
13         
14 5) 迫切左外连接
15 Query q = session.createQuery("from Employee e left join fetch e.department");

1.9、HQL查询优化

1 Query query = session.getNamedQuery("getAllDept"); //定义一个参数名 getAllDept
2 query.setParameter(0, 10);

  然后在对应的xml 配置文件中 写SQL语句。(对于发杂的SQL语句,可以这样做,方便项目发布后,还可以修改)

1 比如在:Employee.hbm.xml 在xml中存放sql语句 2     <query name="getAllDept">  //这里的参数名 getAllDept 要和上面的对应
3         <![CDATA[
4             from Employee d where department_id < ?;  //这里写SQL语句,不是HQL语句
5         ]]>
6     </query>

2、HQL查询语言 实例  

2.1、创建 Employee类、Department类、SubEmployee类、HomeTown类

 1 package com.shore.model;
 2 
 3 import javax.persistence.CascadeType;
 4 import javax.persistence.Entity;
 5 import javax.persistence.GeneratedValue;
 6 import javax.persistence.Id;
 7 import javax.persistence.ManyToOne;
 8 import org.hibernate.annotations.Type;
 9 
10 /**
11  * @author DSHORE/2019-9-25
12  * 多对一,单向关联(注解版)
13  */
14 @Entity
15 public class Employee {//员工  (“多”的一方),在多的一方加外键
16     private Integer id;
17     private String name;
18     private Boolean sex;
19     private Float salary;
20     private Department department;
21     private Integer homeId;
22 
23     @Id
24     @GeneratedValue
25     public Integer getId() {
26         return id;
27     }
28     public void setId(Integer id) {
29         this.id = id;
30     }
31     public String getName() {
32         return name;
33     }
34     public void setName(String name) {
35         this.name = name;
36     }
37 
38     @Type(type="yes_no")
39     public Boolean getSex() {
40         return sex;
41     }
42     public void setSex(Boolean sex) {
43         this.sex = sex;
44     }
45     public Float getSalary() {
46         return salary;
47     }
48     public void setSalary(Float salary) {
49         this.salary = salary;
50     }
51 
52     @ManyToOne(cascade=CascadeType.ALL)
53     public Department getDepartment() {
54         return department;
55     }
56     public void setDepartment(Department department) {
57         this.department = department;
58     }
59 
60     @Override
61     public String toString() {
62         return "Employee [id=" + id + ", name=" + name + ", sex=" + sex
63                 + ", salary=" + salary + ", department=" + department + "]";
64     }
65     public Integer getHomeId() {
66         return homeId;
67     }
68     public void setHomeId(Integer homeId) {
69         this.homeId = homeId;
70     }
71 }

Department类

 1 package com.shore.model;
 2 
 3 import javax.persistence.Entity;
 4 import javax.persistence.GeneratedValue;
 5 import javax.persistence.Id;
 6 
 7 /**
 8  * @author DSHORE/2019-9-25
 9  * 多对一,单向关联(注解版)
10  */
11 @Entity
12 public class Department {//部门 (“一”的一方)
13     private Integer id;
14     private String name;
15     private String description;
16 
17     @Id
18     @GeneratedValue
19     public Integer getId() {
20         return id;
21     }
22     public void setId(Integer id) {
23         this.id = id;
24     }
25     public String getName() {
26         return name;
27     }
28     public void setName(String name) {
29         this.name = name;
30     }
31     public String getDescription() {
32         return description;
33     }
34     public void setDescription(String description) {
35         this.description = description;
36     }
37     @Override
38     public String toString() {
39         return "Department [id=" + id + ", name=" + name + ", description="
40                 + description + "]";
41     }
42 }

SubEmployee类

 1 package com.shore.model;
 2 
 3 /**
 4  * @author DSHORE/2019-9-25
 5  *
 6  */
 7 public class SubEmployee {//查询指定的列,自动封装为对象时 用到(此处不需要创建数据库表)
 8     private String name;
 9     private Boolean sex;
10     private Float salary;
11 
12     public SubEmployee(String name, Boolean sex, Float salary) {
13         super();
14         this.name = name;
15         this.sex = sex;
16         this.salary = salary;
17     }
18 
19     public SubEmployee() {
20         super();
21     }
22 
23     public String getName() {
24         return name;
25     }
26 
27     public void setName(String name) {
28         this.name = name;
29     }
30 
31     public Boolean getSex() {
32         return sex;
33     }
34 
35     public void setSex(Boolean sex) {
36         this.sex = sex;
37     }
38 
39     public Float getSalary() {
40         return salary;
41     }
42 
43     public void setSalary(Float salary) {
44         this.salary = salary;
45     }
46 
47     @Override
48     public String toString() {
49         return "SubEmployee [name=" + name + ", sex=" + sex + ", salary="
50                 + salary + "]";
51     }
52 }

HomeTown类

 1 package com.shore.model;
 2 
 3 /**
 4  * @author DSHORE/2019-9-25
 5  *
 6  */
 7 //后来加入的,没配注解,数据库表和数据都是手动创建的
 8 public class HomeTown {//在使用“连接查询”时用到(内连接、外连接、左/右连接等)
 9     private Integer id;
10     private String address;
11 
12     public Integer getId() {
13         return id;
14     }
15     public void setId(Integer id) {
16         this.id = id;
17     }
18     public String getAddress() {
19         return address;
20     }
21     public void setAddress(String address) {
22         this.address = address;
23     }
24 }

2.2、创建 hibernate.cfg.xml 核心配置文件

 1 <?xml version='1.0' encoding='utf-8'?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7     <session-factory>
 8         <!-- Database connection settings -->
 9         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
10         <property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
11         <property name="connection.username">root</property>
12         <property name="connection.password">123456</property>
13 
14         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
15         <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
16         <property name="show_sql">true</property>
17         <property name="hbm2ddl.auto">update</property>
18 
19         <mapping class="com.shore.model.Employee" />
20         <mapping class="com.shore.model.Department" />
21     </session-factory>
22 </hibernate-configuration>

2.3、开始测试

  1 package com.shore.test;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 import org.hibernate.Query;
  7 import org.hibernate.Session;
  8 import org.hibernate.SessionFactory;
  9 import org.hibernate.Transaction;
 10 import org.hibernate.cfg.AnnotationConfiguration;
 11 import org.junit.AfterClass;
 12 import org.junit.BeforeClass;
 13 import org.junit.Test;
 14 
 15 import com.shore.model.Department;
 16 import com.shore.model.Employee;
 17 
 18 /**
 19  * @author DSHORE/2019-9-19
 20  *
 21  */
 22 public class MyTest {
 23     public static SessionFactory sessionFactory = null;
 24     public static Session session = null;
 25 
 26     @BeforeClass
 27     public static void buildSessionFactory() {
 28         sessionFactory = new AnnotationConfiguration().configure()
 29                 .buildSessionFactory();
 30     }
 31 
 32     @AfterClass
 33     public static void close() {
 34         session.close();
 35         sessionFactory.close();
 36     }
 37 
 38     /**
 39      * 单向多对一:多个员工 对 一个部门
 40      */
 41     /*@Test
 42     public void testAdd() {//插入数据
 43         session = sessionFactory.openSession();
 44         Transaction transaction = session.beginTransaction();
 45         Department dept1 = new Department();
 46         Department dept2 = new Department();
 47         dept1.setName("总裁办");
 48         dept1.setDescription("秘书");
 49         dept2.setName("市场部");
 50         dept2.setDescription("经理");
 51 
 52         Employee em1 = new Employee();
 53         em1.setName("张三");
 54         em1.setSex(true);
 55         em1.setSalary(5999.00f);
 56         em1.setDepartment(dept1);
 57 
 58         Employee em2 = new Employee();
 59         em2.setName("李四");
 60         em2.setSex(true);
 61         em2.setSalary(5999.00f);
 62         em2.setDepartment(dept2);
 63 
 64         Employee em3 = new Employee();
 65         em3.setName("王五");
 66         em3.setSex(true);
 67         em3.setSalary(5999.00f);
 68         em3.setDepartment(dept1);
 69 
 70         Employee em4 = new Employee();
 71         em4.setName("赵六");
 72         em4.setSex(true);
 73         em4.setSalary(5999.00f);
 74         em4.setDepartment(dept1);
 75 
 76         Employee em5 = new Employee();
 77         em5.setName("田七");
 78         em5.setSex(true);
 79         em5.setSalary(5999.00f);
 80         em5.setDepartment(dept2);
 81 
 82         session.save(em1); // 先创建dept1并数据,后创建em1并插入数据
 83         session.save(em2); // 先创建dept2并数据,后插入em2的数据
 84         session.save(em3);
 85         session.save(em4);
 86         session.save(em5);
 87         transaction.commit();
 88     }*/
 89 
 90     /**
 91      * hql :1、查询全部列
 92      */
 93     @SuppressWarnings("unchecked")
 94     @Test
 95     public void testListAllEmployee() {
 96         session = sessionFactory.openSession();
 97         Transaction transaction = session.beginTransaction();
 98         List<Employee> list = new ArrayList<Employee>();
 99         Query query = session.createQuery("select e from Employee e");
100         //或者这样写:Query query = session.createQuery("from Employee"); 效果是一样的
101         list = query.list();
102         transaction.commit();
103 
104         System.out.println("!!!!!!!!!!!!!!");
105         if (list != null && list.size() > 0) {
106             for (int j = 0; j < list.size(); j++) {
107                 System.out.println(j + ":" + list.get(j));
108             }
109         }
110         /** testListAllEmployee()运行结果:
111          * !!!!!!!!!!!!!!
112          * 0:Employee [id=1, name=张三, sex=true, salary=5999.0, department=Department [id=1, name=总裁办, description=秘书]]
113          * 1:Employee [id=2, name=李四, sex=true, salary=5999.0, department=Department [id=2, name=市场部, description=经理]]
114          * 2:Employee [id=3, name=王五, sex=true, salary=5999.0, department=Department [id=1, name=总裁办, description=秘书]]
115          * 3:Employee [id=4, name=赵六, sex=true, salary=5999.0, department=Department [id=1, name=总裁办, description=秘书]]
116          * 4:Employee [id=5, name=田七, sex=true, salary=5999.0, department=Department [id=2, name=市场部, description=经理]]
117          */
118     }
119 
120     /**
121      * hql: 2、查询指定的列
122      */
123     @Test
124     public void testListSubField() {
125         session = sessionFactory.openSession();
126         Transaction transaction = session.beginTransaction();
127         Query query = session.createQuery("select name,sex,salary from Employee");
128         System.out.println(query.list());
129         transaction.commit();
130         /** testListSubField()运行结果:
131          * [[Ljava.lang.Object;@259a8416, [Ljava.lang.Object;@4355d3a3, [Ljava.lang.Object;@37b994de, [Ljava.lang.Object;@78dc9766, [Ljava.lang.Object;@5a57e787]
132          */
133     }
134 
135     /**
136      * hql: 3、查询指定的列,自动封装为对象
137      * 注意:必须要提供带参数构造器;必须在hql封装类前面要加上package名称
138      */
139     @Test
140     public void testListSubFieldsToObj() {
141         session = sessionFactory.openSession();
142         Transaction transaction = session.beginTransaction();
143         Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary) from Employee");
144         System.out.println(query.list());
145         transaction.commit();
146         /** testListSubFieldsToObj()运行结果:
147          * [SubEmployee [name=张三, sex=true, salary=5999.0], SubEmployee [name=李四, sex=true, salary=5999.0], SubEmployee [name=王五, sex=true, salary=5999.0], SubEmployee [name=赵六, sex=true, salary=5999.0], SubEmployee [name=田七, sex=true, salary=5999.0]]
148          */
149     }
150 
151     /**
152      * hql: 4 、条件查询
153      *      4.1、条件查询之占位符(?)
154      */
155     @Test
156     public void testListByConditions1() {
157         session = sessionFactory.openSession();
158         Transaction transaction = session.beginTransaction();
159         Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary) " +
160                         "from Employee where department_id=?"); //用department_id或department都是可以的
161         //query.setParameter(0, 1);//或者下面的setInteger(0, 1)方法也行
162         query.setInteger(0, 1); //类似于JDBC中的 PreparedStatement
163         System.out.println(query.list());
164         transaction.commit();
165         /** testListByConditions1()运行结果:
166          * [SubEmployee [name=张三, sex=true, salary=5999.0], SubEmployee [name=王五, sex=true, salary=5999.0], SubEmployee [name=赵六, sex=true, salary=5999.0]]
167          */
168     }
169     
170     /**
171      * hql: 4.2、条件查询之命名参数(:)
172      */
173     @Test
174     public void testListByConditions2() {
175         session = sessionFactory.openSession();
176         Transaction transaction = session.beginTransaction();
177         Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary) " +
178                         "from Employee where department_id=:deptID");
179         query.setParameter("deptID", 1);
180         System.out.println(query.list());
181         transaction.commit();
182         /** testListByConditions2()运行结果:
183          * [SubEmployee [name=张三, sex=true, salary=5999.0], SubEmployee [name=王五, sex=true, salary=5999.0], SubEmployee [name=赵六, sex=true, salary=5999.0]]
184          */
185     }
186     
187     /**
188      * hql: 4.3、条件查询之范围查询
189      * between 1 and 10    []闭区间  mysql    1<=x<=10
190      */
191     @Test
192     public void testListByConditions3() {
193         session = sessionFactory.openSession();
194         Transaction transaction = session.beginTransaction();
195         Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary) " +
196                         "from Employee where department_id between :d1 and :d2");
197         query.setParameter("d1", 1);   //也可以用占位符?实现
198         query.setParameter("d2", 2);
199         System.out.println(query.list());
200         transaction.commit();
201         /** testListByConditions3()运行结果:
202          * [SubEmployee [name=张三, sex=true, salary=5999.0], SubEmployee [name=王五, sex=true, salary=5999.0], SubEmployee [name=赵六, sex=true, salary=5999.0]]
203          */
204     }
205     
206     /**
207      * hql: 4.4、条件查询之模糊查询  like
208      */
209     @Test
210     public void testListByConditions4() {
211         session = sessionFactory.openSession();
212         Transaction transaction = session.beginTransaction();
213         Query query = session.createQuery("select new com.shore.model.SubEmployee(name,sex,salary) " +
214                         "from Employee where name like ?");
215         query.setParameter(0, "%三%");
216         System.out.println(query.list());
217         transaction.commit();
218         /** testListByConditions4()运行结果:
219          * [SubEmployee [name=张三, sex=true, salary=5999.0]]
220          */
221     }
222     
223     /**
224      * hql: 5、聚合函数统计
225      */
226     @Test
227     public void testListByCount() {
228         session = sessionFactory.openSession();
229         Transaction transaction = session.beginTransaction();
230         Query query = session.createQuery("select count(*) " +
231                         "from Employee where name like ?");
232         query.setParameter(0, "%三%");
233         System.out.println(query.list());
234         transaction.commit();
235         /** testListByCount()运行结果:
236          * [1]
237          */
238     }
239     
240     /**
241      * hql: 6、分组查询group by
242      */
243     @Test
244     public void testListByDept() {
245         session = sessionFactory.openSession();
246         Transaction transaction = session.beginTransaction();
247         Query query = session.createQuery("select department,count(*) " +
248                         "from Employee group by department_id");
249         System.out.println(query.list());
250         transaction.commit();
251         /** testListByDept()运行结果:
252          * [[Ljava.lang.Object;@3b35b1f3, [Ljava.lang.Object;@4235e6e3]
253          */
254     }
255     
256     /**
257      * hql: 7、连接查询
258      *    7.1、内连接 
259      */
260     @Test
261     public void testListByInnerJoin() {
262         session = sessionFactory.openSession();
263         Transaction transaction = session.beginTransaction();
264         Query query = session.createQuery("from Employee e inner join e.department");
265         System.out.println(query.list());
266         transaction.commit();
267         /**
268          * 运行结果:
269          * [[Ljava.lang.Object;@60c9630a, [Ljava.lang.Object;@4585572a, [Ljava.lang.Object;@351daa0e, [Ljava.lang.Object;@2e879860, [Ljava.lang.Object;@4824de7d]
270          */
271     } 
272     
273     /**
274      * 7.2、左连接
275      */
276     @Test
277     public void testListByLeftJoin() {
278         session = sessionFactory.openSession();
279         Transaction transaction = session.beginTransaction();
280         Query query = session.createQuery("from Employee e left join e.department");
281         System.out.println(query.list());
282         transaction.commit();
283         /**
284          * 运行结果:
285          * [[Ljava.lang.Object;@5d15126e, [Ljava.lang.Object;@126d2380, [Ljava.lang.Object;@3b35b1f3, [Ljava.lang.Object;@4235e6e3, [Ljava.lang.Object;@60c9630a]
286          */
287     } 
288     
289     /**
290      * 7.3、右连接
291      */
292     @Test
293     public void testListByRightJoin() {
294         session = sessionFactory.openSession();
295         Transaction transaction = session.beginTransaction();
296         Query query = session.createQuery("from Employee e right join e.department");
297         System.out.println(query.list());
298         transaction.commit();
299         /**
300          * 运行结果:
301          * [[Ljava.lang.Object;@4235e6e3, [Ljava.lang.Object;@60c9630a, [Ljava.lang.Object;@4585572a, [Ljava.lang.Object;@351daa0e, [Ljava.lang.Object;@2e879860]
302          */
303     } 
304 }

数据库表的原数据图:

    

1 SELECT 
2     a.name,a.sex,b.address
3 FROM
4    (SELECT NAME,sex,homeId FROM employee WHERE homeId=1) a 
5 LEFT JOIN
6    (SELECT id,address FROM hometown WHERE id = 1) b
7 ON 
8    a.homeId = b.id; --MySQL语言 左连接查询

结果图:

 

 

 

 

 

 

原创作者:DSHORE

作者主页:http://www.cnblogs.com/dshore123/

原文出自:https://www.cnblogs.com/dshore123/p/11588358.html

欢迎转载,转载务必说明出处。(如果本文对您有帮助,可以点击一下右下角的 推荐,或评论,谢谢!

posted @ 2019-09-25 23:29  DSHORE  阅读(742)  评论(0编辑  收藏  举报