Web开发 | Hibernate - 13.Hibernate框架的查询方式之HQL、QBC(Criteria查询)

一、Hibernate框架的查询方式

1、唯一标识 OID 的检索方式。session.get(类.class,OID)

2、对象的导航的方式。做一对多的环境搭建的时候,Customer 的 JavaBean 定义了 Set集合

HQL 的检索方式 Hibernate Query Language – Hibernate 的查询语言
QBC 的检索方式 Query By Criteria – 条件查询
SQL 检索方式 本地的 SQL 检索

二、HQL查询方式

1、HQL 的介绍
  HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似。
  在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式。

2、HQL 与 SQL 的关系
  HQL 查询语句是面向对象的,Hibernate 负责解析 HQL 查询语句, 然后根据对象-关系映射文件中的映射信息, 把 HQL 查询语句翻译成相应的 SQL 语句.
  HQL 查询语句中的主体是域模型中的类及类的属性(HQL 语句中使用的JavaBean 的类和类中的属性)
  SQL 查询语句是与关系数据库绑定在一起的. SQL 查询语句中的主体是数据库表及表的字段


三、编写常规的JavaBean程序与映射配置文件

SQL的建库、建表

hibernate_day04
这里写图片描述

cst_customer

CREATE TABLE `cst_customer` (
  `cust_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `cust_name` varchar(255) DEFAULT NULL,
  `cust_user_id` varchar(255) DEFAULT NULL,
  `cust_source` varchar(255) DEFAULT NULL,
  `cust_industry` varchar(255) DEFAULT NULL,
  `cust_level` varchar(255) DEFAULT NULL,
  `cust_linkman` varchar(255) DEFAULT NULL,
  `cust_phone` varchar(255) DEFAULT NULL,
  `cust_mobile` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

/*Data for the table `cst_customer` */

insert  into `cst_customer`
(`cust_id`,`cust_name`,`cust_user_id`,`cust_source`,
`cust_industry`,`cust_level`,`cust_linkman`,`cust_phone`,
`cust_mobile`) values 
(1,'邓紫棋',NULL,NULL,NULL,'1',NULL,NULL,NULL),
(2,'吴亦凡',NULL,NULL,NULL,'2',NULL,NULL,NULL),
(3,'鹿晗',NULL,NULL,NULL,'1',NULL,NULL,NULL),
(4,'柯震东',NULL,NULL,NULL,'2',NULL,NULL,NULL),
(5,'杨紫',NULL,NULL,NULL,'1',NULL,NULL,NULL),
(6,'古力娜扎',NULL,NULL,NULL,'2',NULL,NULL,NULL),
(7,'郑秀晶',NULL,NULL,NULL,'1',NULL,NULL,NULL),
(8,'林妙可',NULL,NULL,NULL,'2',NULL,NULL,NULL),
(9,'昆凌',NULL,NULL,NULL,'1',NULL,NULL,NULL),
(10,'李耐阅',NULL,NULL,NULL,'2',NULL,NULL,NULL),
(11,'朴信惠',NULL,NULL,NULL,'1',NULL,NULL,NULL),
(12,'林允儿',NULL,NULL,NULL,'2',NULL,NULL,NULL),
(13,'苍井优',NULL,NULL,NULL,'1',NULL,NULL,NULL),
(14,'宋茜',NULL,NULL,NULL,'2',NULL,NULL,NULL);

cst_customer

cst_linkman

CREATE TABLE `cst_linkman` (
  `lkm_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `lkm_name` varchar(255) DEFAULT NULL,
  `lkm_gender` varchar(255) DEFAULT NULL,
  `lkm_phone` varchar(255) DEFAULT NULL,
  `lkm_mobile` varchar(255) DEFAULT NULL,
  `lkm_email` varchar(255) DEFAULT NULL,
  `lkm_qq` varchar(255) DEFAULT NULL,
  `lkm_position` varchar(255) DEFAULT NULL,
  `lkm_memo` varchar(255) DEFAULT NULL,
  `lkm_cust_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`lkm_id`),
  KEY `FKh9yp1nql5227xxcopuxqx2e7q` (`lkm_cust_id`),
  CONSTRAINT `FKh9yp1nql5227xxcopuxqx2e7q` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;

/*Data for the table `cst_linkman` */

insert  into `cst_linkman`(`lkm_id`,`lkm_name`,`lkm_gender`,`lkm_phone`,
`lkm_mobile`,`lkm_email`,`lkm_qq`,`lkm_position`,`lkm_memo`,
`lkm_cust_id`) values 
(1,'邓紫棋男友1',NULL,NULL,NULL,NULL,NULL,NULL,NULL,1),
(2,'邓紫棋男友2',NULL,NULL,NULL,NULL,NULL,NULL,NULL,1),
(3,'吴亦凡经济人',NULL,NULL,NULL,NULL,NULL,NULL,NULL,2),
(4,'鹿晗麻麻',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3),
(5,'柯震东经济人',NULL,NULL,NULL,NULL,NULL,NULL,NULL,4),
(6,'杨紫 经济人',NULL,NULL,NULL,NULL,NULL,NULL,NULL,5),
(7,'古力娜扎男朋友',NULL,NULL,NULL,NULL,NULL,NULL,NULL,6),
(8,'郑秀晶经济人',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7),
(9,'林妙可爸爸',NULL,NULL,NULL,NULL,NULL,NULL,NULL,8),
(10,'周杰伦',NULL,NULL,NULL,NULL,NULL,NULL,NULL,9),
(11,'李耐阅经济人',NULL,NULL,NULL,NULL,NULL,NULL,NULL,10),
(12,'朴信惠经济人',NULL,NULL,NULL,NULL,NULL,NULL,NULL,11),
(13,'林允儿经济人',NULL,NULL,NULL,NULL,NULL,NULL,NULL,12),
(16,'联系人1',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(17,'联系人2',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

cst_linkman


JavaBean

新建项目Hibernate5_d04_c01,引入必要的jar包、配置、util类

  /Hibernate5_d04_c01/src/hibernate/domain/Customer.java
程序代码如下:

package hibernate.domain;

public class Customer {
    private Long cust_id;
    private String cust_name;
    private Long cust_user_id;
    private Long cust_create_id;
    private String cust_source;
    private String cust_industry;
    private String cust_level;
    private String cust_linkman;
    private String cust_phone;
    private String cust_mobile;

    //set集合表示多个联系人
    private Set<LinkMan> linkMans = new HashSet<>();

    public Set<LinkMan> getLinkMans() {
        return linkMans;
    }
    public void setLinkMans(Set<LinkMan> linkMans) {
        this.linkMans = linkMans;
    }
    public Long getCust_id() {
        return cust_id;
    }
    public void setCust_id(Long cust_id) {
        this.cust_id = cust_id;
    }
    public String getCust_name() {
        return cust_name;
    }
    public void setCust_name(String cust_name) {
        this.cust_name = cust_name;
    }
    public Long getCust_user_id() {
        return cust_user_id;
    }
    public void setCust_user_id(Long cust_user_id) {
        this.cust_user_id = cust_user_id;
    }
    public Long getCust_create_id() {
        return cust_create_id;
    }
    public void setCust_create_id(Long cust_create_id) {
        this.cust_create_id = cust_create_id;
    }
    public String getCust_source() {
        return cust_source;
    }
    public void setCust_source(String cust_source) {
        this.cust_source = cust_source;
    }
    public String getCust_industry() {
        return cust_industry;
    }
    public void setCust_industry(String cust_industry) {
        this.cust_industry = cust_industry;
    }
    public String getCust_level() {
        return cust_level;
    }
    public void setCust_level(String cust_level) {
        this.cust_level = cust_level;
    }
    public String getCust_linkman() {
        return cust_linkman;
    }
    public void setCust_linkman(String cust_linkman) {
        this.cust_linkman = cust_linkman;
    }
    public String getCust_phone() {
        return cust_phone;
    }
    public void setCust_phone(String cust_phone) {
        this.cust_phone = cust_phone;
    }
    public String getCust_mobile() {
        return cust_mobile;
    }
    public void setCust_mobile(String cust_mobile) {
        this.cust_mobile = cust_mobile;
    }
}

  /Hibernate5_d04_c01/src/hibernate/domain/LinkMan.java
程序代码如下:

package hibernate.domain;

public class LinkMan {
    private Integer lkm_id;
    private String lkm_name;
    //lkm_cust_id 外键,不用写
    private String lkm_gender;
    private String lkm_phone;
    private String lkm_mobile;
    private String lkm_email;
    private String lkm_qq;
    private String lkm_position;
    private String lkm_memo;

    //客户类
    private Customer customer;

    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
    public Integer getLkm_id() {
        return lkm_id;
    }
    public void setLkm_id(Integer lkm_id) {
        this.lkm_id = lkm_id;
    }
    public String getLkm_name() {
        return lkm_name;
    }
    public void setLkm_name(String lkm_name) {
        this.lkm_name = lkm_name;
    }
    public String getLkm_gender() {
        return lkm_gender;
    }
    public void setLkm_gender(String lkm_gender) {
        this.lkm_gender = lkm_gender;
    }
    public String getLkm_phone() {
        return lkm_phone;
    }
    public void setLkm_phone(String lkm_phone) {
        this.lkm_phone = lkm_phone;
    }
    public String getLkm_mobile() {
        return lkm_mobile;
    }
    public void setLkm_mobile(String lkm_mobile) {
        this.lkm_mobile = lkm_mobile;
    }
    public String getLkm_email() {
        return lkm_email;
    }
    public void setLkm_email(String lkm_email) {
        this.lkm_email = lkm_email;
    }
    public String getLkm_qq() {
        return lkm_qq;
    }
    public void setLkm_qq(String lkm_qq) {
        this.lkm_qq = lkm_qq;
    }
    public String getLkm_position() {
        return lkm_position;
    }
    public void setLkm_position(String lkm_position) {
        this.lkm_position = lkm_position;
    }
    public String getLkm_memo() {
        return lkm_memo;
    }
    public void setLkm_memo(String lkm_memo) {
        this.lkm_memo = lkm_memo;
    }
}

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

package hibernate.test;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import hibernate.domain.Customer;
import hibernate.domain.LinkMan;
import hibernate.util.HibernateUtils;

public class TestHQL {
    private Session session;
    private Transaction tr;
    private String hql ;
    private List<Customer> list;

    @Before
    public void init(){
        session = HibernateUtils.getCurrentSession();
        tr = session.beginTransaction();
    }

    @After
    public void destroy(){ 
        tr.commit();
    }
}

映射配置文件

  /Hibernate5_d04_c01/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <class name="hibernate.domain.Customer" table="cst_customer">
        <!-- 主键对应 -->
        <id name="cust_id" column="cust_id">
            <!-- 主键策略(与自增长相关) -->
            <generator class="native"></generator>
        </id>
        <!-- 其他字段 -->
        <property name="cust_name" column="cust_name"></property>
        <property name="cust_user_id" column="cust_user_id"></property>
        <property name="cust_create_id" column="cust_create_id"></property>
        <property name="cust_source" column="cust_source"></property>
        <property name="cust_industry" column="cust_industry"></property>
        <property name="cust_level" column="cust_level"></property>
        <property name="cust_linkman" column="cust_linkman"></property>
        <property name="cust_phone" column="cust_phone"></property>
        <property name="cust_mobile" column="cust_mobile"></property>
        <!-- 一对多配置 -->
        <set name="linkMans" inverse="true"  >
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>

    </class>
</hibernate-mapping>

  /Hibernate5_d04_c01/src/hibernate/domain/LinkMan.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="hibernate.domain.LinkMan" table="cst_linkman">
        <id name="lkm_id" column="lkm_id">
            <generator class="native"></generator>
        </id>
        <property name="lkm_name" column="lkm_name"></property>
        <property name="lkm_gender" column="lkm_gender"></property>
        <property name="lkm_phone" column="lkm_phone"></property>
        <property name="lkm_mobile" column="lkm_mobile"></property>
        <property name="lkm_email" column="lkm_email"></property>
        <property name="lkm_qq" column="lkm_qq"></property>
        <property name="lkm_position" column="lkm_position"></property>
        <property name="lkm_memo" column="lkm_memo"></property>
        <!-- 多方配置 -->
        <many-to-one name="customer" class="hibernate.domain.Customer"
        column="lkm_cust_id" ></many-to-one>
    </class>
</hibernate-mapping>

  /Hibernate5_d04_c01/src/hibernate.cfg.xml
程序代码如下:

<?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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/hibernate_day04</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
                <!--数据库方言 使用的数据库类型  -->
        <property name="hibernate.dialect org.hibernate.dialect.MySQLDialect"></property>

        <!-- 可选配置 -->
                <!-- 在控制台输出sql语句 -->
        <property name="show_sql">true</property>
                <!-- 在控制台输出的sql语句格式化 -->
        <property name="hibernate.format_sql">true</property>
                <!-- 配置c3p0连接池 -->
                    <!-- C3P0 的供应商 -->
        <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
                    <!-- 最小连接 -->
        <property name="hibernate.c3p0.min_size">5</property>
                    <!-- 最大连接数 -->
        <property name="hibernate.c3p0.max_size">10</property>
                    <!-- 每 120 秒检查空闲连接 -->
        <property name="hibernate.c3p0.timeout">120</property>
                <!-- 自动建表 -->
        <property name="hibernate.hbm2ddl.auto">update</property>
                <!-- 把session绑定到当前线程中,使用getCurrentSession()获取当前session -->
        <property name="hibernate.current_session_context_class">thread</property>

        <!-- 映射文件 -->
        <mapping resource="hibernate/domain/Customer.hbm.xml"/>
        <mapping resource="hibernate/domain/LinkMan.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

四、HQL基本的查询格式

1、基本查询

  支持方法链的编程,即直接调用 list()方法
    session.createQuery("from Customer").list();

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //1.HQL基本的查询格式
    @Test
    public void testHql1(){
        //1.必须写实体类,不能写表名
        //Customer 指的是 java 类,hibernate 通过 javabean 来操作数据库
        hql = "from Customer";

        //2.通过 session 的 createQuery 方法执行 hql语句
        Query query = session.createQuery(hql);

        //3.调用 list 方法获取集合值,使用泛型接收
        list = query.list();

        //4.遍历
        for (Customer customer : list) {
            System.out.println(customer.getCust_id()+"-->"+customer.getCust_name()+"-->"+customer.getCust_level());
        }
    }
}

运行效果
运行效果

因为testHql1()方法中的2、3、4步骤是可以与其他查询语句共用
所以可以将其封装成一个方法:print()

选中代码后右键
选中代码后右键
封装成print方法
封装成print方法

封装后代码的变动如下

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //1.HQL基本的查询格式
    @Test
    public void testHql1(){
        //1.必须写实体类,不能写表名
        //Customer 指的是 java 类,hibernate 通过 javabean 来操作数据库
        hql = "from Customer";
        print();
    }

    private void print() {
        //2.通过 session 的 createQuery 方法执行 hql语句
        Query query = session.createQuery(hql);

        //3.调用 list 方法获取集合值,使用泛型接收
        list = query.list();

        //4.遍历
        for (Customer customer : list) {
            System.out.println(customer.getCust_id()+"-->"+customer.getCust_name()+"-->"+customer.getCust_level());
        }
    }
}

2、别名查询
session.createQuery("from Customer c").list();
或session.createQuery("select c from Customer c").list();

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //2.使用别名的方式
    //可以单独查询某几个字段
    @Test
    public void testHql2(){
        //必须写实体类,不能写表名
        //hql = "from Customer c";
        hql = "select c from Customer c";
        print();
    }

    private void print() {
        ...
    }
}

3、排序查询
排序查询和 SQL 语句中的排序的语法是一样的
升序:session.createQuery("from Customer order by cust_id").list();
降序:ession.createQuery("from Customer order by cust_id desc").list();

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //3.排序查询
    @Test
    public void testHql3(){
        //升序
        //hql = "from Customer order by cust_id ";
        //降序
        hql = "from Customer order by cust_id desc";
        print();
    }

    private void print() {
        ...
    }
}

4、分页查询
Hibernate框架提供了分页的方法,可以调用方法来完成分页
两个方法如下:
setFirstResult(a) -- 从哪条记录开始,如果查询是从第一条开启,值是0
setMaxResults(b) -- 每页查询的记录条数

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //4.分页查询
    @Test
    public void testHql4(){
        hql = "from Customer";
        Query query = session.createQuery(hql);
        //1.设置分页
        //  设置起始索引
        //  从第2条记录开始
        query.setFirstResult(1);
        //2.设置每页查询的记录条数
        query.setMaxResults(3);
        //获取的id为234的记录

        //3.遍历
        list = query.list();
        for (Customer customer : list) {
            System.out.println(customer.getCust_id()+"-->"+customer.getCust_name()+"-->"+customer.getCust_level());
        }
    }

    private void print() {
        ...
    }
}

因为testHql4()方法中的3步骤是可以与其他查询语句共用
所以可以将其封装成一个方法print1()
封装成一个方法print1()
封装成一个方法print1()

封装后代码的变动如下

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //4.分页查询
    @Test
    public void testHql4(){
        hql = "from Customer";
        Query query = session.createQuery(hql);
        //1.设置分页
        //  设置起始索引
        //  从第2条记录开始
        query.setFirstResult(1);
        //2.设置每页查询的记录条数
        query.setMaxResults(3);
        //获取的id为2、3、4的记录

        print1(query);
    }

    private void print1(Query query) {
        //3.遍历
        list = query.list();
        for (Customer customer : list) {
            System.out.println(customer.getCust_id()+"-->"+customer.getCust_name()+"-->"+customer.getCust_level());
        }
    }

    private void print() {
        //2.通过 session 的 createQuery 方法执行 hql语句
        Query query = session.createQuery(hql);
        print1(query);
    }
}

5、条件查询
setParameter("?号的位置,默认从 0 开始","参数的值"); 不用考虑参数的具体类型
按位置绑定参数的条件查询(指定下标值,默认从 0 开始)
按名称绑定参数的条件查询(HQL 语句中的 ? 号换成 :名称 的方式)

?占位符

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //5.带条件的查询1
    @Test
    public void testHql5(){
        //找出所有姓林的明星
        hql = "from Customer where cust_name like ?";
        Query query = session.createQuery(hql);
        //设置?占位符的值
        //第一个参数 ?的索引
        //第二个参数 ?对应的值
        query.setParameter(0, "林%");
        print1(query);
    }

    ...
    private void print1(Query query) {
        ...
    }
}

:name 占位符

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //6.带条件的查询2
    @Test
    public void testHql6(){
        //找出所有姓林的明星
        hql = "from Customer where cust_name like :name";
        Query query = session.createQuery(hql);
        //设置:name占位符的值
        //第一个参数:具体替换占位值
        //第二个参数:替换的内容
        query.setParameter("name", "林%");
        print1(query);
    }
    ...
    private void print1(Query query) {
        ...
    }
}

五、HQL的投影查询

  投影查询就是想查询某一字段的值或者某几个字段的值

1、投影查询1

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //1.投影查询1
    @Test
    public void testHql7(){
        //查找所有明星的姓名和级别
        hql = "select c.cust_name,c.cust_level from Customer c";
        Query query = session.createQuery(hql);
        //这里不能用print(Query)方法来打印
        //因为返回的是Object数组,需要使用Object数组来接收
        //List data = query.list();
        List<Object[]> data = query.list();
        for (Object[] objects : data) {
            System.out.println(objects[0]+"-->"+objects[1]);
        }
    }
    ...
    private void print1(Query query) {
        ...
    }
}

查看返回的是什么类型的数据
查看返回的是什么类型的数据


2、投影查询2

如果查询两个字段,也可以把这两个字段封装到对象中

1、先在持久化类中提供对应字段的构造方法
2、使用下面这种HQL语句的方式

  /Hibernate5_d04_c01/src/hibernate/domain/Customer.java
程序代码如下:

package hibernate.domain;

import java.util.HashSet;
import java.util.Set;

public class Customer {
    ...
    //set集合表示多个联系人
    private Set<LinkMan> linkMans = new HashSet<>();

    /**  
    * @Title: Customer
    * 需要提供一个空的构造方法,hibernate 默认使用空的构造方法来创建对象      
    */
    public Customer() {
        // TODO Auto-generated constructor stub
    }
    /**  
    * @Title: Customer  
    * @param cust_name
    * @param cust_level    
    */
    public Customer(String cust_name, String cust_level) {
        this.cust_name = cust_name;
        this.cust_level = cust_level;
    }
    ...
}

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //2.投影查询2
    @Test
    public void testHql8(){
        //如果查询两个字段,也可以把这两个字段封装到对象中
        //先在持久化类中提供对应字段的构造方法
        hql = "select new Customer(c.cust_name,c.cust_level) from Customer c";
        Query query = session.createQuery(hql);
        print1(query);
    }
    ...
    private void print1(Query query) {
        ...
    }
}

六、HQL的聚合函数查询

uniqueResult() 唯一的结果。
如果查询的结果只包含一个对象,使用uniqueResult(),
如果查询结果包含多个对象,使用uniqueResult抛出异常。
1、聚合函数查询1

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //1.聚合函数查询1
    //获取总的记录数
    @Test
    public void testHql9(){
        hql = "select count(c) from Customer c";
        Query query = session.createQuery(hql);
        //因为返回的是Long类型的数,需要使用Long来接收
        //Object o = (Long) query.uniqueResult();
        Long o = (Long) query.uniqueResult();
        System.out.println(o);
    }
    ...
    private void print1(Query query) {
        ...
    }
}

查看返回的是什么类型的数据
查看返回的是什么类型的数据


2、聚合函数查询2

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //2.聚合函数查询2
    //获取某一列数据的和
    @Test
    public void testHql10(){
        hql = "select sum(c.cust_id) from Customer c";
        Query query = session.createQuery(hql);
        Long o = (Long) query.uniqueResult();
        System.out.println(o);
    }
    ...
    private void print1(Query query) {
        ...
    }
}

3、分组查询

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //3.分组查询
    //对客户等级分组
    @Test
    public void testHql11(){
        hql = "select c.cust_level  from Customer c group by c.cust_level";
        Query query = session.createQuery(hql);
        //断点查看返回的是什么类型的数据
        List<Object> data  = query.list();
        //System.out.println(data);
        //输出[1, 2]
        for (Object object : data) { 
            System.out.println(object);
        }
        //输出
        //1
        //2
    }
    ...
    private void print1(Query query) {
        ...
    }
}

七、HQL的多表查询

多表的查询进来使用 HQL 语句进行查询,HQL 语句和 SQL 语句的查询语法比较类似。
    内连接查询
        显示内连接
            select * from customers c inner join orders oon c.cid = o.cno;
        隐式内连接
            select * from customers c,orders o where c.cid = o.cno;
    外连接查询
        左外连接
            select * from customers c left join orders o onc.cid = o.cno;
        右外连接
            select * from customers c right join orders o onc.cid = o.cno;

1、内连接查询

内连接使用 inner join,返回的是 Object 数组

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //1.内连接查询
    //查询所有客户及对应的联系人(有关联关系的)
    @Test
    public void testHql12(){
        //显示内连接
        hql = "from Customer c inner join c.linkMans";
        Query query = session.createQuery(hql);
        //断点查看返回的是什么类型的数据
        //返回的是Object数组
        List<Object[]> data  = query.list();
        for (Object[] objects : data) {
            Customer c = (Customer) objects[0];
            LinkMan m = (LinkMan) objects[1];
            System.out.println(c.getCust_name()+"-->"+m.getLkm_name());
        }
    }
    ...
    private void print1(Query query) {
        ...
    }
}

2、迫切内连接

迫切内连接使用 inner join fetch,返回的是实体对象

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //2.迫切内连接
    //查询所有客户及对应的联系人(有关联关系的)
    @Test
    public void testHql13(){
        hql = "from Customer c inner join fetch c.linkMans";
        Query query = session.createQuery(hql);
        //断点查看返回的是什么类型的数据
        //返回的是实体对象
        List<Customer> data  = query.list();
        for (Customer customer : data) {
            System.out.println(customer.getCust_name()+"-->"+customer.getLinkMans().size());
        }
    }
    ...
    private void print1(Query query) {
        ...
    }
}

3、左外连接查询

左外连接使用 left join,返回的是 Object 数组

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //3.左外连接
    //查询所有客户及对应的联系人(没有关联关系+有关联关系的)
    @Test
    public void testHql14(){
        hql = "from Customer c left join c.linkMans";
        Query query = session.createQuery(hql);
        //断点查看返回的是什么类型的数据
        //返回的是Object数组
        List<Object[]> data  = query.list();
        for (Object[] objects : data) {
            Customer c = (Customer) objects[0];
            System.out.println(c.getCust_name()+"-->"+c.getLinkMans().size());
        }
    }
    ...
    private void print1(Query query) {
        ...
    }
}

4、迫切左外连接

迫切内连接使用 left join fetch,返回的是实体对象

  /Hibernate5_d04_c01/src/hibernate/test/TestHQL.java
程序代码如下:

...
public class TestHQL {
    ...
    //4.迫切左外连接
    //查询所有客户及对应的联系人(没有关联关系+有关联关系的)
    @Test
    public void testHql15(){
        hql = "from Customer c left join fetch c.linkMans";
        Query query = session.createQuery(hql);
        //断点查看返回的是什么类型的数据
        //返回的是实体对象
        List<Customer> data  = query.list();
        for (Customer customer : data) {
            System.out.println(customer.getCust_name()+"-->"+customer.getLinkMans().size());
        }
    }
    ...
    private void print1(Query query) {
        ...
    }
}

八、QBC查询方式(做条件查询非常合适)

  1、QBC:Query By Criteria – 按条件进行查询。

  2、QBC 查询方式的使用

1、先创建查询的接口 
Criteria c = session.createCriteria(User.class);
2、设置查询的条件 
criteria.add(Restrictions.gt("age", 10));
3、查询数据 
List<User> list = criteria.list();

九、编写常规的JavaBean程序与映射配置文件

新建项目Hibernate5_d04_c02

  1、数据库及数据表同HQL一样
  2、拷贝项目Hibernate5_d04_c01的jar包、配置、util类、domain类


十、QBC基本的查询格式

1、基本查询

  简单查询:使用的是 Criteria 接口
  /Hibernate5_d04_c02/src/hibernate/test/TestQBC.java
程序代码如下:

package hibernate.test;

import java.util.Arrays;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.sql.JoinType;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import hibernate.domain.Customer;
import hibernate.util.HibernateUtils;

public class TestQBC {
    private Session session;
    private Transaction tr;
    private String hql ;
    private List<Customer> list;

    @Before
    public void init(){
        session = HibernateUtils.getCurrentSession();
        tr = session.beginTransaction();
    }

    @After
    public void destroy(){ 
        tr.commit();
    }

    //1.简单查询,使用的是Criteria接口
    //查询所有客户信息
    @Test
    public void testQBC1(){
        Criteria criteria = session.createCriteria(Customer.class);
        print(criteria);
    }

    private void print(Criteria criteria) {
        //调用list方法获取集合值,使用泛型接收
        list = criteria.list();
        //遍历
        for (Customer customer : list) {
            System.out.println(customer.getCust_id()+"-->"+customer.getCust_name()+"-->"+customer.getCust_level());
        }
    }

}

2、排序查询
需要使用addOrder()的方法来设置参数,
参数使用org.hibernate.criterion.Customer对象

  /Hibernate5_d04_c02/src/hibernate/test/TestQBC.java
程序代码如下:

...
public class TestQBC {
    ...
    //2.排序查询
    @Test
    public void testQBC2(){
        Criteria criteria = session.createCriteria(Customer.class);
        //添加排序条件
        criteria.addOrder(Order.desc("cust_id"));
        print(criteria);
    }

    private void print(Criteria criteria) {
        ...
    }
}

3、分页查询
QBC的分页查询也是使用两个方法
setFirstResult();
setMaxResults();

  /Hibernate5_d04_c02/src/hibernate/test/TestQBC.java
程序代码如下:

...
public class TestQBC {
    ...
    //3.分页查询
    @Test
    public void testQBC3(){
        Criteria criteria = session.createCriteria(Customer.class);
        //设置分页条件
        criteria.setFirstResult(1);
        criteria.setMaxResults(3);
        print(criteria);
    }

    private void print(Criteria criteria) {
        ...
    }
}

4、条件查询
Criterion 是查询条件的接口。
Restrictions 类是 Hibernate 框架提供的工具类,用来设置查询条件。
条件查询使用 Criteria 接口的 add 方法,用来传入条件。
Restrictions.eq 相等
Restrictions.gt 大于号
Restrictions.ge 大于等于
Restrictions.lt 小于
Restrictions.le 小于等于
Restrictions.between 在之间
Restrictions.like 模糊查询
Restrictions.in 范围
Restrictions.and 并且
Restrictions.or 或者

  /Hibernate5_d04_c02/src/hibernate/test/TestQBC.java
程序代码如下:

...
public class TestQBC {
    ...
    //4.条件查询
    //查询所有等级为2或者姓名中带邓的客户
    @Test
    public void testQBC4(){
        Criteria criteria = session.createCriteria(Customer.class);
        criteria.add(Restrictions.or(
                Restrictions.eq("cust_level", "2"),
                Restrictions.like("cust_name", "邓%")
                ));
        print(criteria);
    }

    private void print(Criteria criteria) {
        ...
    }
}

十一、QBC的聚合函数查询

Projection 的聚合函数的接口,
而 Projections 是 Hibernate 提供的工具类,
使用该工具类设置聚合函数查询。

使用 QBC 的聚合函数查询,
需要使用 criteria.setProjection() 方法
1、聚合函数查询1

  /Hibernate5_d04_c02/src/hibernate/test/TestQBC.java
程序代码如下:

...
public class TestQBC {
    ...
    //1.聚合函数查询1
    //查询所有客户的数量
    @Test
    public void testQBC5(){
        Criteria criteria = session.createCriteria(Customer.class);
        //使用聚合函数查询
        criteria.setProjection(Projections.rowCount());
        Long count = (Long) criteria.uniqueResult();
        System.out.println(count);
    }

    private void print(Criteria criteria) {
        ...
    }
}

2、聚合函数查询2
聚合函数的查询
criteria.setProjection(Projections.sum("cust_id"));
多次设置该方法,默认会覆盖。

解决覆盖的问题 : 
ProjectionList projectionList = Projections.projectionList(); 
向集合中添加聚合函数的设置。

  /Hibernate5_d04_c02/src/hibernate/test/TestQBC.java
程序代码如下:

...
public class TestQBC {
    ...
    //2.聚合函数查询2
    //查询所有客户的数量以及cust_id的和
    @Test
    public void testQBC6(){
        Criteria criteria = session.createCriteria(Customer.class);
        //使用聚合函数查询
        //这样写后面一个条件会覆盖前面一个条件
        //criteria.setProjection(Projections.rowCount());
        //criteria.setProjection(Projections.sum("cust_id"));
        //使用 ProjectionList来解决这个问题
        //ProjectionList可以存储多个条件
        ProjectionList list = Projections.projectionList();
        list.add(Projections.rowCount());
        list.add(Projections.sum("cust_id"));
        criteria.setProjection(list);
        Object[] data = (Object[]) criteria.uniqueResult();
        //System.out.println(data[0]+"-->"+data[1]);
        //输出14-->105
        System.out.println(Arrays.toString(data));
        //输出[14, 105]
    }   

    private void print(Criteria criteria) {
        ...
    }
}

3、分组查询

  /Hibernate5_d04_c02/src/hibernate/test/TestQBC.java
程序代码如下:

...
public class TestQBC {
    ...
    //3.分组查询
    //分组+统计
    @Test
    public void testQBC7(){
        Criteria criteria = session.createCriteria(Customer.class);
        //使用聚合函数查询
        //ProjectionList来存储多个条件
        ProjectionList list = Projections.projectionList();
        //添加分组条件
        list.add(Projections.groupProperty("cust_level"));
        //添加统计条件
        list.add(Projections.rowCount());
        //设置条件列表
        criteria.setProjection(list);
        List<Object[]> data = criteria.list();
        for (Object[] objects : data) {
            //System.out.println(objects[0]+"-->"+objects[1]);
            //1-->7
            //2-->7
            System.out.println(Arrays.toString(objects));
            //[1, 7]
            //[2, 7]
        }
    }   

    private void print(Criteria criteria) {
        ...
    }
}

十二、QBC的多表查询

  /Hibernate5_d04_c02/src/hibernate/test/TestQBC.java
程序代码如下:

...
public class TestQBC {
    ...
    //多表查询
    //查询每个用户对应联系人的数量(有关联关系的)
    @Test
    public void testQBC8(){
        Criteria criteria = session.createCriteria(Customer.class);
        //设置内连接查询
        //第一个参数是客户类中联系人属性
        //第二个参数是连接类型
        criteria.createCriteria("linkMans", JoinType.INNER_JOIN);
        List<Customer> customers = criteria.list();
        for (Customer customer : customers) {
            System.out.println(customer.getCust_name()+"-->"+customer.getLinkMans().size());
        }
    }   

    private void print(Criteria criteria) {
        ...
    }
}

十三、SQL 查询方式

  /Hibernate5_d04_c02/src/hibernate/test/TestQBC.java
程序代码如下:

...
public class TestQBC {
    ...
    //SQL查询方式
    @Test
    public void testSql(){
        //查询客户表中数据
        String sql ="select * from cst_customer where cust_id > ?";
        SQLQuery query = session.createSQLQuery(sql);
        //设置条件参数
        query.setParameter(0, 2L);
        //把返回数据加入实体类中
        query.addEntity(Customer.class);
        list = query.list();
        for (Customer customer : list) {
            System.out.println(customer.getCust_name()+"-->"+customer.getLinkMans().size());
        }
    }   

    private void print(Criteria criteria) {
        ...
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的影城管理系统,源码+数据库+论文答辩+毕业论文+视频演示 随着现在网络的快速发展,网上管理系统也逐渐快速发展起来,网上管理模式很快融入到了许多生活之中,随之就产生了“小徐影城管理系统”,这样就让小徐影城管理系统更加方便简单。 对于本小徐影城管理系统的设计来说,系统开发主要是采用java语言技术,在整个系统的设计中应用MySQL数据库来完成数据存储,具体根据小徐影城管理系统的现状来进行开发的,具体根据现实的需求来实现小徐影城管理系统网络化的管理,各类信息有序地进行存储,进入小徐影城管理系统页面之后,方可开始操作主控界面,主要功能包括管理员:首页、个人中心、用户管理、电影类型管理、放映厅管理、电影信息管理、购票统计管理、系统管理、订单管理,用户前台;首页、电影信息、电影资讯、个人中心、后台管理、在线客服等功能。 本论文主要讲述了小徐影城管理系统开发背景,该系统它主要是对需求分析和功能需求做了介绍,并且对系统做了详细的测试和总结。具体从业务流程、数据库设计和系统结构等多方面的问题。望能利用先进的计算机技术和网络技术来改变目前的小徐影城管理系统状况,提高管理效率。 关键词:小徐影城管理系统;Spring Boot框架,MySQL数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值