OID和对象导航方式

例:

1
2
3
4
5
6
7
8
9
10
public void run1(){
Session session = HibernateUtils.getSession();
Transaction tr = session.beginTransaction();
//唯一OID方式查询客户
Customer c = session.get(Customer.class, 1L);
//对象导航方式
System.out.println(c.getLinkMans().size());
tr.commit();
}

HQL

HQL查询方式

  1. 介绍
    HQL(Hibernate Query Language) 是面向对000000象的查询语言, 它和SQL 查询语言有些相似,在Hibernate提供的各种检索方式中,HQL是使用最广的一种检索方式。
  2. HQL与SQL的关系
    • HQL查询语句是面向对象的,Hibernate负责解析HQL查询语句,然后根据对象-关系映射文件中的映射信息, 把HQL查询语句翻译成相应的SQL语句.
    • HQL查询语句中的主体是域模型中的类及类的属性
    • SQL查询语句是与关系数据库绑定在一起的
    • SQL查询语句中的主体是数据库表及表的字段
  3. HQL的简单查询

    1. 基本查询

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      /**
      * 基本查询
      */
      @Test
      public void run1(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      //创建HQL查询的接口
      Query query = session.createQuery("from Customer");
      List<Customer> list = query.list();
      for (Customer customer : list) {
      System.out.println(customer);
      }
      tr.commit();
      }
    2. 支持方法链的编程查询
      可以在createQuery方法后面跟多个方法传入参数如list()

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      /**
      * 支持方法链的编程
      */
      @Test
      public void run2(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      //支持方法链,在后面接.list
      List<Customer> list = session.createQuery("from Customer").list();
      for (Customer customer : list) {
      System.out.println(customer);
      }
      tr.commit();
      }
    3. 支持别名方式查询

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      /**
      * 支持别名方式
      * 同SQL
      */
      @Test
      public void run3(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      //select c可省略,千万不要加*
      List<Customer> list = session.createQuery("select c from Customer c where c.cust_id=1").list();
      for (Customer customer : list) {
      System.out.println(customer);
      }
      tr.commit();
      }
    4. 排序查询

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      /**
      * 排序查询
      * order by 属性名 asc/desc
      */
      @Test
      public void run4(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      /* //升序排列
      List<LinkMan> list = session.createQuery("from LinkMan l order by lkm_id asc").list();*/
      //降序排列
      List<LinkMan> list = session.createQuery("from LinkMan l order by lkm_id desc").list();
      for (LinkMan linkman : list) {
      System.out.println(linkman);
      }
      tr.commit();
      }
    5. 分页查询

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      /**
      * 分页查询
      * 起始页:setFirstResult(a)
      * 页大小:setMaxResults(b)
      */
      @Test
      public void run5(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      /*//第一页,设置起始页为0,每页记录3条数据
      List<LinkMan> list = session.createQuery("from LinkMan l order by lkm_id desc").setFirstResult(0).setMaxResults(3).list();*/
      //第二页,设置起始页为3,每页记录3条数据
      List<LinkMan> list = session.createQuery("from LinkMan l order by lkm_id desc").setFirstResult(3).setMaxResults(3).list();
      for (LinkMan linkman : list) {
      System.out.println(linkman);
      }
      tr.commit();
      }
    6. 带条件的查询

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      /**
      * 条件查询查询
      */
      @Test
      public void run6(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      /*//按位置绑定参数?的条件查询(指定下标值,默认从0开始)
      List<LinkMan> list = session.createQuery("from LinkMan l where lkm_id > ?").setLong(0,3L).list();*/
      /*//按名称绑定参数的条件查询(HQL语句中的 ? 号换成 :名称 的方式)
      List<LinkMan> list = session.createQuery("from LinkMan l where lkm_id > :id").setLong("id", 2L).list();*/
      //不用考虑参数的具体类型setParameter("?号的位置,默认从0开始","参数的值")
      List<LinkMan> list = session.createQuery("from LinkMan l where lkm_id > ? and lkm_name = ?").setParameter(0, 2L).setParameter(1, "四号").list();
      for (LinkMan linkman : list) {
      System.out.println(linkman);
      }
      tr.commit();
      }
  4. 投影查询
    投影查询就是想查询某一字段的值或者某几个字段的值

    1. 直接查询

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      /**
      * 投影查询:只查询几个字段,不是所有字段
      * 相当于sql的"select id,name from LinkMan"
      * 直接查询
      */
      @Test
      public void run8(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      List<Object[]> list = session.createQuery("select lkm_name,lkm_id from LinkMan").list();
      for (Object[] objects : list) {
      System.out.println(Arrays.toString(objects));
      }
      tr.commit();
      }
    2. 封装到对象中查询

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      /**
      *在LinkMan中添加以下构造函数
      */
      //投影查询,空的构造函数不能省略
      public LinkMan(){
      }
      //投影查询,传入要查询字段对应的参数
      public LinkMan(long lkm_id, String lkm_name) {
      super();
      this.lkm_id = lkm_id;
      this.lkm_name = lkm_name;
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      /**
      * 投影查询:只查询几个字段 ,不是所有字段
      * 相当于sql的"select id, name from LinkMan"
      * 封装到对象中查询
      * 第一步:需要在JavaBean 类提供对应的构造方法
      * 第二步:修改HQL语句
      */
      @Test
      public void run7(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      List<LinkMan> list = session.createQuery("select new LinkMan(lkm_id,lkm_name) from LinkMan").list();
      for (LinkMan linkman : list) {
      System.out.println(linkman);
      }
      tr.commit();
      }
  5. 聚合函数查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /**
    * 聚合函数
    * sum() count() avg() max() min()
    * 查询联系人的数量
    */
    @Test
    public void run9(){
    Session session = HibernateUtils.getSession();
    Transaction tr = session.beginTransaction();
    //count(别名) = count(*)
    List<Number> list = session.createQuery("select count(l) from LinkMan l").list();
    //通过下标取值,longValue()改变类型
    System.out.println(list.get(0).longValue());
    tr.commit();
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /**
    * 聚合函数
    * sum() count() avg() max() min()
    * 查询联系人id的和
    */
    @Test
    public void run10(){
    Session session = HibernateUtils.getSession();
    Transaction tr = session.beginTransaction();
    //count(别名) = count(*)
    List<Number> list = session.createQuery("select sum(lkm_id) from LinkMan l").list();
    //通过下标取值,longValue()改变类型
    System.out.println(list.get(0).longValue());
    tr.commit();
    }

HQL多表查询

内连接

简介:查询两表之间的交集(有关联)部分,默认返回object[]数组
代码实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 内连接:查询两表之间的交集(有关联)部分
* 客户对象 inner join 客户对象的联系人集合
* 默认返回object[]数组
* 查询客户,客户和联系人有关联
*/
@Test
public void run1(){
Session session = HibernateUtils.getSession();
Transaction tr = session.beginTransaction();
//创建HQL的查询接口
Query query = session.createQuery("from Customer c inner join c.LinkMans");
List<Object[]> list = query.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
tr.commit();
}

迫切内连接

简介:查询两表之间的交集(有关联)部分,返回对应的实体对象
代码实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 迫切内连接:查询两表之间的交集(有关联)部分
* 客户对象 inner join fetch客户对象的联系人集合
* 返回对应的实体对象
* 把对象封装在Set集合,去掉重复数据
* 查询客户,客户和联系人有关联
*/
@Test
public void run2(){
Session session = HibernateUtils.getSession();
Transaction tr = session.beginTransaction();
//创建HQL的查询接口
Query query = session.createQuery("from Customer c inner join fetch c.LinkMans");
List<Customer> list = query.list();
//手动去掉重复数据
Set<Customer> set = new HashSet<Customer>(list);
for (Customer customer : set) {
System.out.println(customer);
}
tr.commit();
}

左(右)外连接

简介:查询左(右)表和两表之间交集(关联)部分,默认返回object[]数组
代码实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 左外连接:查询左表和两表之间交集(关联)部分
* 客户对象 left join 客户对象的联系人集合
* 默认返回object[]数组
* 查询客户,客户和联系人有关联
*/
@Test
public void run3(){
Session session = HibernateUtils.getSession();
Transaction tr = session.beginTransaction();
//创建HQL的查询接口
Query query = session.createQuery("from Customer c left join c.LinkMans");
List<Object[]> list = query.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
tr.commit();
}

迫切左(右)外连接

简介:查询左(右)表和两表之间交集(关联)部分,返回实体对象
代码实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 迫切左外连接:查询左表和两表之间交集(关联)部分
* 客户对象 left join fetch客户对象的联系人集合
* 返回对应的实体对象
* 把对象封装在Set集合,去掉重复数据
* 查询客户,客户和联系人有关联
*/
@Test
public void run4(){
Session session = HibernateUtils.getSession();
Transaction tr = session.beginTransaction();
//创建HQL的查询接口
Query query = session.createQuery("from Customer c left join fetch c.LinkMans");
List<Customer> list = query.list();
//手动去掉重复数据
Set<Customer> set = new HashSet<Customer>(list);
for (Customer customer : set) {
System.out.println(customer);
}
tr.commit();
}

QBC

QBC查询方式

  1. 简介
    QBC查询即Query By Criteria,按条件查询
  2. 简单查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /**
    * 基本查询
    */
    @Test
    public void run1(){
    Session session = HibernateUtils.getSession();
    Transaction tr = session.beginTransaction();
    //创建QBC查询接口
    Criteria criteria = session.createCriteria(LinkMan.class);
    //查询所有值
    List<LinkMan> list = criteria.list();
    for (LinkMan linkMan : list) {
    System.out.println(linkMan);
    }
    tr.commit();
    }
  3. 排序查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    /**
    * 排序查询
    * 使用addOrder()设置参数
    */
    @Test
    public void run2(){
    Session session = HibernateUtils.getSession();
    Transaction tr = session.beginTransaction();
    //创建QBC查询接口
    Criteria criteria = session.createCriteria(LinkMan.class);
    //添加排序desc or
    criteria.addOrder(Order.desc("lkm_id"));
    criteria.addOrder(Order.asc("lkm_id"));
    //查询所有值
    List<LinkMan> list = criteria.list();
    for (LinkMan linkMan : list) {
    System.out.println(linkMan);
    }
    tr.commit();
    }
  4. 分页查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
    * 分页查询
    * setFirstResult()和setMaxResult()
    * 起始页和页的大小
    */
    @Test
    public void run3(){
    Session session = HibernateUtils.getSession();
    Transaction tr = session.beginTransaction();
    //创建QBC查询接口
    Criteria criteria = session.createCriteria(LinkMan.class);
    //设置每一页三条数据
    criteria.setFirstResult(0);
    criteria.setMaxResults(3);
    //查询所有值
    List<LinkMan> list = criteria.list();
    for (LinkMan linkMan : list) {
    System.out.println(linkMan);
    }
    tr.commit();
    }
  5. 条件查询

    • 简介:Criterion是查询条件的接口,Restrictions类是Hibernate框架提供的工具类,使用该工具类来设置查询条件
    • 条件查询使用Criterion接口的add方法,用来传入条件
    • 使用Restrictions的添加条件的方法来添加条件
    • 常见的条件
      • Restrictions.eq – 相等
      • Restrictions.gt – 大于号
      • Restrictions.ge – 大于等于
      • Restrictions.lt – 小于
      • Restrictions.le – 小于等于
      • Restrictions.between – 在之间
      • Restrictions.like – 模糊查询
      • Restrictions.in – 范围
      • Restrictions.and – 并且
      • Restrictions.or – 或者
      • Restrictions.isNull – 是否等于null
    • 代码实例
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      /**
      * 条件查询
      * 使用Criterion接口的add方法,用来传入条件
      * 多个条件就用多个add添加条件
      * 使用Restrictions的添加条件的方法来添加条件
      */
      @Test
      public void run4(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      //创建QBC查询接口
      Criteria criteria = session.createCriteria(LinkMan.class);
      //查询lkm_id=1L的值或lkm_id>4L的值
      criteria.add(Restrictions.or(Restrictions.gt("lkm_id", 4L), Restrictions.eq("lkm_id", 1L)));
      //查询3-5之间的值
      criteria.add(Restrictions.between("lkm_id", 3L, 5L));
      //查询所有值
      List<LinkMan> list = criteria.list();
      for (LinkMan linkMan : list) {
      System.out.println(linkMan);
      }
      tr.commit();
      }
  6. 聚合函数查询

    • 简介:Projection的聚合函数的接口,而Projections是Hibernate提供的工具类,使用该工具类设置聚合函数查询。
    • 使用QBC的聚合函数查询,需要使用criteria.setProjection()方法。
    • 代码实例
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      /**
      * 聚合函数查询
      * 注:在查询完聚合函数后,要继续查询其他字段的话要设置回默认
      */
      @Test
      public void run5(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      //创建QBC查询接口
      Criteria criteria = session.createCriteria(LinkMan.class);
      //设置聚合函数的方式
      List<Number> list = criteria.setProjection(Projections.count("lkm_id")).list();
      Long count = list.get(0).longValue();
      System.out.println(count);
      //继续查询其他字段的话要设置回默认
      criteria.setProjection(null);
      List<LinkMan> list2 = criteria.list();
      for (LinkMan linkMan : list2) {
      System.out.println(linkMan);
      }
      tr.commit();
      }
  7. 离线条件查询

    • 简介:离线条件查询使用的是DetachedCriteria接口进行查询,离线条件查询对象在创建的时候,不需要使用Session对象,只是在查询的时候使用Session对象即可
    • 代码实例
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      /**
      * 离线条件查询
      * 注:脱离session,可以不使用session来创建离线查询对象,只在查询的时候需要Session对象
      */
      @Test
      public void run6(){
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      //创建离线查询接口
      DetachedCriteria criteria = DetachedCriteria.forClass(LinkMan.class);
      //添加条件
      criteria.add(Restrictions.gt("lkm_id", 3L));
      //查询数据
      List<LinkMan> list = criteria.getExecutableCriteria(session).list();
      for (LinkMan linkMan : list) {
      System.out.println(linkMan);
      }
      tr.commit();
      }

SQL

  1. 简介
    直接使用SQL语句进行查询
  2. 代码实例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    /**
    * SQL基本查询
    * 把数据封装到对象
    */
    @Test
    public void run(){
    Session session = HibernateUtils.getSession();
    Transaction tr = session.beginTransaction();
    String sql = "select * from cst_linkman where lkm_id = ?";
    //创建SQL的查询接口
    SQLQuery query = session.createSQLQuery(sql);
    query.setParameter(0, 1L);
    //设置数据封装对象
    query.addEntity(LinkMan.class);
    List<LinkMan> list = query.list();
    for (LinkMan linkMan : list) {
    System.out.println(linkMan);
    }
    tr.commit();
    }

延迟加载

延迟加载先获取到代理对象,当真正使用到该对象中的属性的时候,才会发送SQL语句,是Hibernate框架提升性能的方式。

  1. 类级别的延迟加载

    • Session对象的load方法默认就是延迟加载
    • 只有在使用该对象属性时才发送SQL语句

      • 代码实例
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        /**
        * 类级别的延迟加载
        * 只有在使用该对象属性时才发送SQL语句
        */
        @Test
        public void run() {
        Session session = HibernateUtils.getSession();
        Transaction tr = session.beginTransaction();
        //开启类级别的延迟加载
        Customer c = session.load(Customer.class,1L);
        System.out.println("-----------");
        System.out.println(c.getCust_name());
        tr.commit();
        }
    • 使类级别的延迟加载失效

      • 在该类的配置文件的标签添加lazy=”false”
      • 添加语句Hibernate.initialize(Object proxy);
      • 代码实例
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        /**
        * 使类级别的延迟加载失效的两种方式
        * 1.在该类的配置文件的<class>标签添加lazy="false"
        * 2.添加语句Hibernate.initialize(Object proxy);
        */
        @Test
        public void run2() {
        Session session = HibernateUtils.getSession();
        Transaction tr = session.beginTransaction();
        //开启类级别的延迟加载
        Customer c = session.load(Customer.class,1L);
        //直接初始化c对象,使其延迟加载失效
        Hibernate.initialize(c); //在这会有SQL语句
        System.out.println("-----------");
        System.out.println(c.getCust_name());
        tr.commit();
        }
  2. 关联级别的延迟加载

    • 默认为延迟加载
    • 查询客户时,不会把联系人信息查询出来,而是在用到客户中的联系人时才会发送SQL语句
    • 代码实例
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      /**
      * 关联级别的延迟加载
      * 默认就是延迟加载
      * 客户中的联系人信息只有在用到的时候才会发送SQL语句
      */
      @Test
      public void run3() {
      Session session = HibernateUtils.getSession();
      Transaction tr = session.beginTransaction();
      Customer c = session.get(Customer.class, 1L);
      Set<LinkMan> mans = c.getLinkMans();
      for (LinkMan linkMan : mans) {
      System.out.println(linkMan);
      }
      tr.commit();
      }

配置查询策略

  • 使用Hibernate查询一个对象的时候,查询其关联对象应该如何查询是Hibernate的一种优化手段!
  • lazy属性解决查询的时机的问题,需要配置是否采用延迟加载
  • fetch属性就解决查询语句的形式问题

在set标签上配置策略

  • fetch的取值:控制SQL语句生成的格式
    • select:默认值,发送基本select语句查询
    • join:连接查询,发送的是一条迫切左外连接,配置了join会使lazy属性失效!
    • subselect:子查询,发送一条子查询查询其关联对象。(需要使用list()方法进行测试)
  • lazy的取值 :查找关联对象的时候是否采用延迟!
    • true:默认值,延迟加载
    • false:不延迟加载
    • extra :及其懒惰,sql语句会精简化
  • fetch的默认值为:select,lazy的默认值为true
  • 在开发中基本上使用默认值,特殊情况除外

标签上配置策略

  • fetch的取值:控制SQL语句生成的格式
    • select:默认值,发送基本select语句查询
    • join:连接查询,发送迫切左外连接查询,配置了join会使lazy属性失效!
  • lazy的取值:控制加载关联对象是否采用延迟。
    • false:不采用延迟加载。
    • proxy:默认值,代理。由另一端的上的lazy值来确定是否延迟加载,如果那端的class上的lazy=”true”则proxy相当于true(延迟加载),如果那端class上的lazy=”false”,则proxy相当于false(不延迟加载)