(十二)Hibernate的查询方式

一、OID检索方式

 

1
2
3
按照对象的OID来查询对象。Session的get/load方法提供了这种功能。
 
如果应用程序中事先知道了OID,就可以使用这种查询对象的方式。

 

  

二、导航对象图检索方式

 

1
2
3
根据已经加载的对象,导航到其他对象.
 
例如,对于已经加载的Customer对象,可以导航到所有关联的Order对象

 

  

三、HQL检索方式

 

简介:

 

使用面向对象的HQL查询语言。Hibernate提供了Query接口,它是专门的HQL查询接口,能执行各种复杂的HQL语句。

 

HQL是面向对象的查询语言,和SQL查询语言有些类似,Hibernate提供的各种检索方式中,HQL是使用最广的一种检索方式。HQL封装了JDBC的细节

1
2
3
4
5
HQL和SQL本质是不一样的:
 
    -HQL查询语言面向对象,Hibernate负责解析HQL语句,然后根据映射文件,把HQL语句翻译成SQL语句。HQL查询语句中主体是类和类的属性。
 
    -SQL查询语言是和关系数据库绑定在一起的,SQL查询语句中主体是数据库表和表的字段。

  

HQL查询的步骤 
-通过session的createQuery(HQL语句)方法创建一个Query对象 
-调用Query的list()方法执行查询语句。该方法返回List集合

 

(1)================= 查找所有对象 ====================

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Demo {
 
                private Session session;
 
                @Test
                public void test() {
                    //读取配置文件
                    Configuration conf=new Configuration().configure();
 
                    //根据配置创建factory
                    SessionFactory sessionfactory=conf.buildSessionFactory();
                    session = sessionfactory.openSession();
                     Transaction ts=session.beginTransaction();
                     //HQL语句是面向对象的,from 类名
                    List<Customer> customerlist=session.createQuery("from Customer").list();
                    System.out.println(customerlist);
                    ts.commit();
                    session.close();
                    sessionfactory.close();
                }
 
            }

  (2)================= HQL语句使用别名 ====================

1
2
3
例如:List< Customer > customerlist=session.createQuery(“from Customer as c”).list();
 
as关键字用来设置别名,as也可以省略。 from Customer c即可。

  (3)================= HQL语句选择查询 ====================

1
2
3
4
5
6
7
选择查询是指仅查找某些属性。
这时list()返回的集合中包括的是一个一个数组,每个数组中是一条记录。
 
List <Object[]> customerlist=session.createQuery("select id,name from Customer").list();
for(Object[] obj:customerlist){
    System.out.println(Arrays.toString(obj));
}

  (4)================= HQL语句投影查询 ====================

1
2
3
4
5
6
7
8
9
10
11
12
13
基于选择查询的基础上,把查询到的属性封装到对象中,该对象的其他属性为null
该对象必须有对应的构造方法。
 
List <Customer> customerlist=session.createQuery("select new Customer(id,name) from Customer").list();
for(Customer c:customerlist){
    System.out.println(c.toString());
}
 
Customer类中必须有如下构造方法    
public Customer(Integer id, String name) {
    this.id = id;
    this.name = name;
}

  (5)================= HQL对查询结果排序 ====================

1
2
3
4
HQL语言使用order by关键字对结果进行排序。
asc为升序,desc为降序。
 
List <Customer> customerlist=session.createQuery("select new Customer(id,name) from Customer order by id desc").list();

  (6)================= HQL分页查询 ====================

1
2
3
4
5
6
7
8
9
-setFirstResult(int index):设定从第几个对象开始检索,起始值为0
-setMaxResult(int count):设定一次检索的对象数目。默认情况下检索所有的对象。
 
    Query query=session.createQuery("select id,name from Customer");
    //从第一个对象开始
    query.setFirstResult(0);
    //查找两个对象
    query.setMaxResults(2);
    List result=query.list();

  (7)================= HQL语句中绑定参数 ====================

1
2
3
对于实际应用中,经常需要用户输入一些查询条件,我们返回符合查询条件的数据。
我们可以使用from Customer where name='"+name+"';来实现
但是这种方式是非常不安全的,会受到SQL注入等非法攻击。

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Hibernate中使用参数绑定来避免以上问题。有两种方式
 
(1)使用?占位符绑定
                占位符的索引从0开始。
                Query query=session.createQuery("from Customer where id=?");
                query.setInteger(0, 7);
 
                Customer c=(Customer) query.uniqueResult();
                System.out.println(c.toString());
 
                Query提供了各种绑定数据类型的参数的方法setXxx(),如果参数为字符串类型,就调用setString(),如果参数为整数类型,就调用setInteger()等等。
                这些setXxx()方法第一个参数代表占位符的索引,第二个代表参数值。
 
(2) 使用参数名字绑定
                在HQL中使用命名参数,命名参数以":"开头。
                Query query=session.createQuery("from Customer where id=:a");
                query.setInteger("a", 7);
 
                Customer c=(Customer) query.uniqueResult();
                System.out.println(c.toString());
 
                这些setXxx()方法第一个参数是命名参数的名字,第二个参数是值。

  (8)================= HQL查询单个对象 ====================

1
2
3
4
5
-uniqueResult()方法:返回单个对象 
 
        Query query=session.createQuery("from Customer where id=1");
        Customer c=(Customer) query.uniqueResult();
        System.out.println(c.toString());

  (9)================= HQL聚合函数和分组查询 ====================

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(1)HQL调用聚合函数
        -查询customer表所有记录数目
                    Query query=session.createQuery("select count(*) from Customer");
                    //该语句返回long类型
                    Long c=(Long) query.uniqueResult();
                    System.out.println(c.intValue());
 
        -查询最大ID
                    Query query=session.createQuery("select Max(id) from Customer");
                    Integer c=(Integer) query.uniqueResult();
                    System.out.println(c.intValue());
 
 
(2)分组查询
        group by子句用来分组查询。
 
        -根据id分组,统计相同id的数目
                    Query query=session.createQuery("select id,count(*) from Customer group by id");
                    List<Object[]> list=query.list();
                    for(Object[] obj:list){
                        System.out.println(Arrays.toString(obj));
                    }
 
        -having子句用于为分组查询加上条件
                    Query query=session.createQuery("select id,count(*) from Customer group by id having id>8");
                    List<Object[]> list=query.list();
                    for(Object[] obj:list){
                        System.out.println(Arrays.toString(obj));
                    }

  (10)================= HQL连接查询 ====================

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
-交叉连接:返回被连接的两个表所有数据行的笛卡儿积
如果A表有5行记录,B表有7行记录,返回的结果就有35行记录
显然,会产生很多没有意义的数据。
 
        Query query=session.createQuery("from Customer,Order");
        List<Object[]> list=query.list();
        for(Object[] obj:list){
            System.out.println(Arrays.toString(obj));
        }
 
-隐式内连接
    在交叉连接基础上,通过条件来过滤一些无意义的数据,达到内连接的效果。
        Query query=session.createQuery("from Customer c,Order o where o.customer=c");
        List<Object[]> list=query.list();
        for(Object[] obj:list){
            System.out.println(Arrays.toString(obj));
        }
 
-显式内连接
    使用inner join关键字表示内连接。inner可以省略,只使用join。
    调用list()方法返回的集合中存放的是每个元素对应的记录,每个元素都是数组类型。
 
        Query query=session.createQuery("from Customer c inner join c.orders");
        List<Object[]> list=query.list();
        for(Object[] obj:list){
            System.out.println(Arrays.toString(obj));
        }
 
 
-迫切内连接
    使用inner join fetch关键字表示迫切内连接。
    调用list()方法返回的集合中存放的是Customer对象的引用,每个Customer对象的Orders集合都被初始化,存放所有关联的Order对象。
 
        Query query=session.createQuery("from Customer c inner join  c.orders");
        List <Object> list=query.list();
        for(Object obj:list){
            System.out.println(obj);
        }
 
-左外连接
    在连接查询中,连接左端的表中的所有的行全部显示,并且能在右端的表中找到匹配的行,如果右端表中没能找到左端匹配的行,则对应NULL.
    使用left join关键字表示左外连接。
    返回的list集合中存放的是多个对象数组。  
    Query query=session.createQuery("from Customer c left join  c.orders");
    List<Object[]> list=query.list();
    for(Object[] obj:list){
        System.out.println(Arrays.toString(obj));
    }
 
-迫切左外连接
    使用left join fetch关键字表示迫切左外连接。
    list()方法返回的集合中存放的是Customer对象的引用,每个Customer的Orders集合都被初始化,存放关联的Order对象。
        Query query=session.createQuery("from Customer c left join fetch c.orders");
        List<Object> list=query.list();
        for(Object obj:list){
            System.out.println(obj);
        }
 
-右外连接
    和左外连接一样,连接右端表中的行全部显示,连接左端找到匹配的行,如果未能找到匹配的行,则用NULL代替
    使用right join关键字表示右外连接。
    Query query=session.createQuery("from Customer c right join  c.orders");
    List<Object[]> list=query.list();
    for(Object[] obj:list){
        System.out.println(Arrays.toString(obj));
    }
 
-迫切右外连接
    Query query=session.createQuery("from Customer c right join fetch  c.orders");
    List<Object> list=query.list();
    for(Object obj:list){
        System.out.println(obj);
    }

  (11)================= 在映射文件中定义命名查询语句 ====================

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
前面的例子中,HQL查询语句都写在程序代码中。Hibernate允许在映射文件中定义字符串形式的查询语句。
 
            <class name="com.cad.domain.Customer" table="customer" >
                <id name="id" column="id">
                    <generator class="native"></generator>
                </id>
                <property name="name" column="name"></property>
                <set name="orders" batch-size="3" fetch="subselect">
                    <key column="cid"/>
                    <one-to-many class="com.cad.domain.Order" />   
                </set>
                <!--定义局部命名查询语句-->
                <query name="bcd"><![CDATA[from Order]]></query>
            </class>
            <!--定义全局命名查询语句-->
            <query name="abc"><![CDATA[from Customer]]></query>
 
            //调用全局的命名查询语句
            Query query=session.getNamedQuery("abc");
            //调用局部的命名查询语句
            Query query=session.getNamedQuery("com.cad.domain.Customer.bcd");
            List<Object> list=query.list();
            for(Object obj:list){
                System.out.println(obj);
            }

 

 

四、QBC检索方式

 

1
2
3
4
5
6
使用QBC(Query By Criteria)API检索对象。封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。
 
QBC检索方式的步骤
        -调用Session的createCriteria()方法创建一个Criteria对象
        -设定查询条件
        -调用Criteria接口的list()方法执行查询语句。返回List集合。

 

  (1)================= 查询所有对象 ====================

1
2
3
4
5
6
//传递类名.class即可
Criteria criteria=session.createCriteria(Customer.class);
List<Customer> l=criteria.list();
 for(Customer c:l){
     System.out.println(c);
 }

  (2)================= QBC对查询结果进行排序 ====================

1
2
3
4
5
6
7
8
9
QBC使用org.hibernate.criterion.order类对查询结果排序。
asc为升序,desc为降序。
 
 Criteria criteria=session.createCriteria(Customer.class);
 criteria.addOrder(org.hibernate.criterion.Order.desc("id"));
 List<Customer> l=criteria.list();
 for(Customer c:l){
     System.out.println(c);
 }

  (3)================= QBC分页查询 ====================

1
2
3
4
5
6
7
8
9
10
11
QBC的分页查询和HQL类似。Criteria接口也提供了方法。
        -setFirstResult(int index):设定从第几个对象开始检索,起始值为0
        -setMaxResult(int count):设定一次检索的对象数目。默认情况下检索所有的对象。
 
             Criteria criteria=session.createCriteria(Customer.class);
             criteria.setFirstResult(0);
             criteria.setMaxResults(2);
             List<Customer> l=criteria.list();
             for(Customer c:l){
                 System.out.println(c);
             }

  (4)================= QBC设定查询条件 ====================

1
2
3
4
5
6
7
8
9
10
11
12
必须创建一个Criterion对象来设定查询条件。Restrictions类提供了创建Criterion的方法。
        -Restrictions.eq()  等于
        -Restrictions.ne() 不等于
        -Restrictions.gt()  大于
          ..........等等很多方法
 
    Criteria criteria=session.createCriteria(Customer.class);
    //查询id为7的Customer
     Criterion c1=Restrictions.eq("id", 7);
     criteria.add(c1);
     Customer c=(Customer) criteria.uniqueResult();
     System.out.println(c);

  (5)================= QBC检索单个对象 ====================

1
uniqueResult():返回单个对象

  

 

五、本地SQL检索方式

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
可以使用原生的SQL语句来进行查询。
本地SQL检索也是使用Query接口,通过Session的createSQLQuery(SQL语句)方法来创建Query。
 
    例子:
        Query query =session.createSQLQuery("select * from customer");
         List<Object[]> list=query.list();
         for(Object[] o:list){
 
 
             System.out.println(Arrays.toString(o));
         }
 
        默认情况下,SQLQuery返回的list集合中存放的是关系数据。每个元素都是Object[]数组。
 
    -addEntity()方法能把查询结果中每一行的数据封装成对象
 
            Query query =session.createSQLQuery("select * from customer").addEntity(Customer.class);
             List<Customer> list=query.list();
             for(Customer o:list){
                 System.out.println(o.toString());
             }

 

  

 

 

  

 

posted @   跃小云  阅读(207)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示