JAVAEE框架学习——Hibernate——事务 查询API应用、查询优化

Hibernate 事物

Hibernate是对JDBC的轻量封装,主要功能是操作数据库。

Hibernate中的事物管理

在Hibernate中,可以通过API接口来操作管理事物。可以通过session.beginTransaction()开启一个事物,持久化操作后,通过commit()提交事物。如果事物异常,通过rollback()来进行事物的回滚。
除了在代码中对事物开启,提交和回滚操作外,还可以在Hibernate的配置文件中对事物进行配置。配置文件中,可以设置事物的隔离级别。


事物隔离级别
  • 在hibernate.cfg.xml文件中的标签元素中进行配置
 
        4

基本点:在项目中如何管理事物:

在项目中,通过经验我们有一个基本的认识:
在业务开始之前打开事物,在业务执行之后提交事物,执行过程中如果出现异常,则回滚事物

  • 在dao层操作数据库的时候需要用到session对象,在service控制事物也是使用session对象完成,所以我们要确保dao层和service层使用的是同一个session对象
    注意1:调用getCurrentSession方法必须配合主配置中的一段配置
   
        thread

注意2:通过getCurrentSession方法获得的Session对象,当事物提交时,session会自动关闭,不需要手动调用close关闭,session会自动被回收

Hibernate 查询API

HQL查询

HQL(Hibernate Query Language) 是面向对象的查询语言。使用的是类、对象和属性的概念。没有表和字段的概念。Hibernate提供的Query接口是专门的HQL查询接口,能够执行各种复杂的HQL查询语句。
由于HQL是面向对象的,所以不会出现和表名列名有关的语句。应该使用的是对象名 属性名

  • 完整的HQL语句
select...from...where...group...by...having...order by...asc/desc

当检索数据表中的所有记录时,查询语句中可以省略select关键字

获得Hibernate的Session对象
编写HQL语句
调用session.createQuery 创建查询对象
通过Query的setXxx设置参数
调用Query对象的list()或uniqueResult()执行查询

查询所有记录

  //编写HQL语句
String hql = "from cn.probuing.domain.Customer";
//根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//根据查询对象获得
List list = query.list();//返回list

排序查询

  /**
     * 排序语法
     */
    @Test
    public void HQLSort(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        String hql = "from cn.probuing.domain.Customer order by cust_id desc";
        Query query = session.createQuery(hql);
        List list = query.list();
        System.out.println(list);
        tx.commit();
        session.close();
    }

根据条件进行查询

 /**
     * 条件查询
     */
    @Test
    public void HQLCondition(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
//        String hql = "from cn.probuing.domain.Customer order where cust_id=?";
        String hql2 = "from cn.probuing.domain.Customer order where cust_id=:id";//另一种写法
        Query query = session.createQuery(hql2);
        //设置占位符
//        query.setParameter(0,2);
        //另一种占位符写法
        query.setParameter("id",2);
        List list = query.list();
        System.out.println(list);
        tx.commit();
        session.close();
    }

分页查询

  /**
     * 分页查询
     */
    @Test
    public void HQLPage(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
//        String hql = "from cn.probuing.domain.Customer order where cust_id=?";
        String hql2 = "from cn.probuing.domain.Customer";//另一种写法
        Query query = session.createQuery(hql2);
        //表示从0条开始
        query.setFirstResult(0);
        //表示查找2条
        query.setMaxResults(2);
        List list = query.list();
        System.out.println(list);
        tx.commit();
        session.close();
    }

聚合函数

   /**
     * 聚合函数
     */
    @Test
    public void HQLCount() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
//        String hql = "from cn.probuing.domain.Customer order where cust_id=?";
        String hql2 = "select count(*) from cn.probuing.domain.Customer";
        //求和 指定列名
        String hql3 = "select sum(cust_id) from cn.probuing.domain.Customer";
        String hql4 = "select avg(cust_id) from cn.probuing.domain.Customer";
        String hql5 = "select max(cust_id) from cn.probuing.domain.Customer";
        String hql6 = "select min(cust_id) from cn.probuing.domain.Customer";
        Query query = session.createQuery(hql4);
        Number number = (Number) query.uniqueResult();
        System.out.println(number);
        tx.commit();
        session.close();
    }

投影查询

查询对象的某一个属性

 @Test
    public void testHQLDemo2() {
        Session session = HibernateUtils.openSession();
        //开启事物
        Transaction transaction = session.beginTransaction();


        //编写HQL语句
//        String hql = "from cn.probuing.domain.Customer where cust_id =? ";
        String hql = "from cn.probuing.domain.Customer where cust_id = :cust_id ";
        //根据HQL语句创建查询对象
        Query query = session.createQuery(hql);
        //设置参数 指定类型
//        query.setLong(0,1l);
        //设置参数 不指定参数
//        query.setParameter(0,1l);
        //根据参数名设置参数
        query.setParameter("cust_id", 1l);
        //根据查询对象获得
        Customer customer = (Customer) query.uniqueResult();//接收唯一的查询结果
        System.out.println(customer.toString());
        //提交事物,关闭资源
        transaction.commit();
        session.close();
    }

在指定条件时有以下几个方法:

  • 指定参数需要使用setXxx()指定类型
  • 不指定参数需要使用setParameter(占位符索引,值)
  • 根据名称指定条件值 setparameter(名称,值)

分页查询

hql语句中没有limit(?,?)这样的语句,需要使用API方法来实现分页的功能

  • setFirstResult() 设置起始的位置
  • setMaxResult() 设置最大的条数
   public void testHQLDemo3() {
        Session session = HibernateUtils.openSession();
        //开启事物
        Transaction transaction = session.beginTransaction();
        String hql = "from cn.probuing.domain.Customer ";
        //根据HQL语句创建查询对象
        Query query = session.createQuery(hql);
        //设置起始信息
        query.setFirstResult(0);
        //设置最大条数
        query.setMaxResults(2);
        //根据查询对象获得
        List list = query.list();
        System.out.println(list.toString());
        //提交事物,关闭资源
        transaction.commit();
        session.close();
    }

Criteria查询

Criteria是一个完全面向对象,可扩展的条件查询API,通过它完全不需要考虑数据库底层如何实现,以及SQL语句如何编写。Criteria查询又称为QBC查询。它是Hibernate的另一种对象检索方式
org.hibernate.criterion.Criterion是Hibernate提供的一个面向对象查询条件接口。一个单独的查询就是Criterion接口的一个实例。用于限制Criteria对象的查询。在Hibernate中Criterion对象的创建时通过Restriction工厂类完成

主要步骤:

(1) 获得Hibernate的Session对象
(2) 通过Session获得Criteria对象
(3) 使用Restriction的静态方法创建Criterion条件对象。Restrictions类中提供了一系列用于设定查询条件的静态方法
(4) 向Criteria对象中添加Criterion查询条件

基本查询

//获得session
        Session session = HibernateUtils.openSession();
        //通过session获得Criteria对象 参数表示指定查询所有的Customer对象
        Criteria criteria = session.createCriteria(Customer.class);
        //使用Restrictions对象进行查询 返回集合
        List list = criteria.list();
        //返回单个结果
//        Customer customer = (Customer) criteria.uniqueResult();
        System.out.println(list.toString());

条件查询

 @Test
    public void testHQLDemo4() {
        //获得session
        Session session = HibernateUtils.openSession();
        //通过session获得Criteria对象 参数表示指定查询所有的Customer对象
        Criteria criteria = session.createCriteria(Customer.class);


        //调用add方法添加参数 => 查询cust_id 为1的Customer对象
        criteria.add(Restrictions.eq("cust_id", 1l));
        // 条件:>
        //使用Restrictions对象进行查询 返回集合
//        List list = criteria.list();
        //返回单个结果
        Customer customer = (Customer) criteria.uniqueResult();


        System.out.println(customer.toString());
        session.close();

    }

对应条件API:

条件查询

分页查询

/**
     * Criteria 查询
     */
    @Test
    public void testHQLDemo4() {
        //获得session
        Session session = HibernateUtils.openSession();
        //通过session获得Criteria对象 参数表示指定查询所有的Customer对象
        Criteria criteria = session.createCriteria(Customer.class);
        //指定起始
        criteria.setFirstResult(0);
        criteria.setMaxResults(2);
//        使用Restrictions对象进行查询 返回集合
        List list = criteria.list();
        System.out.println(list.toString());
        session.close();
    }

查询总记录数

  @Test
    public void testHQLDemo4() {
        //获得session
        Session session = HibernateUtils.openSession();
        //通过session获得Criteria对象 参数表示指定查询所有的Customer对象
        Criteria criteria = session.createCriteria(Customer.class);
        //设置查询的聚合函数
        criteria.setProjection(Projections.rowCount());
        Long result = (Long) criteria.uniqueResult();
        System.out.println(result);
        session.close();
    }

排序查询

  @Test
    public void BaseCriteriaOrder() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //操作数据
        //创建criteria
        Criteria criteria = session.createCriteria(Customer.class);
        criteria.addOrder(Order.asc("cust_id"));
//        criteria.addOrder(Order.desc("cust_id"));
        List list = criteria.list();
        System.out.println(list);
        tx.commit();
        session.close();
    }

原生SQL查询

普通查询

  @Test
    public void sqlQuery() {
        Session session = HibernateUtils.openSession();
        //开启事物
        Transaction tx = session.beginTransaction();
        //书写SQL语句
        String sql = "select * from cst_customer";
        //创建查询对象
        SQLQuery query = session.createSQLQuery(sql);
        //封装对象:将结果集指定封装对象
        query.addEntity(Customer.class);
        //查询结果 接收封装对象集合
//        List list = query.list();
        //查询结果 未指定封装对象
        List list = query.list();
        System.out.println(list.toString());
        tx.commit();
        session.close();
    }

条件查询

 @Test
    public void sqlQuery() {
        Session session = HibernateUtils.openSession();
        //开启事物
        Transaction tx = session.beginTransaction();
        //书写SQL语句
        String sql = "select * from cst_customer where cust_id = ?";

        //创建查询对象
        SQLQuery query = session.createSQLQuery(sql);
        //设置参数
        query.setParameter(0, 1);
        //指定封装对象
        query.addEntity(Customer.class);
        List list = query.list();
        System.out.println(list.toString());
        tx.commit();
        session.close();
    }

分页查询

   public void sqlQuery() {
        Session session = HibernateUtils.openSession();
        //开启事物
        Transaction tx = session.beginTransaction();
        //书写SQL语句
        String sql = "select * from cst_customer limit ?,? ";
        //创建查询对象
        SQLQuery query = session.createSQLQuery(sql);
        //设置条件参数
        query.setParameter(0, 0);
        query.setParameter(1,1);
        //封装对象:将结果集指定封装对象
        query.addEntity(Customer.class);
        //查询结果 接收封装对象集合
        List list = query.list();
        //查询结果 未指定封装对象
//        List list = query.list();
        System.out.println(list.toString());
        tx.commit();
        session.close();
    }

离线查询

DetachedCriteria翻译为离线条件查询,它可以脱离session来使用的一种条件查询对象


传统查询
  • 传统的查询方式过于依赖session对象。减少参数的传递。


    离线查询

使用离线查询思路为:
在web层或者service层不依赖session创建查询对象Criteria。并设置好条件等相关参数
传递Criteria对象到Dao层
Dao层将离线的Criteria对象与session关联。关联后会将离线的Criteria对象转换为普通的Criteria对象。
通过普通的Criteria对象执行数据操作

实例代码

 @Test
    public void fun1() {
        //模拟service层或web层
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
        //拼装好条件
        detachedCriteria.add(Restrictions.idEq(2l));
        //dao层
        Session session = HibernateUtils.openSession();
        //离线对象关联session 关联session后 就会由离线的Criteria对象变为普通的Criteria对象
        Criteria c = detachedCriteria.getExecutableCriteria(session);
        //执行查询
        List list = c.list();
        System.out.println(list);
    }

查询优化

类级别查询优化

延迟加载

类级别的延迟指的是查询某个对象的时候,是否采用有延迟。通常在标签上配置lazy属性,lazy属性的默认值是true

  • lazy:true 加载时,不查询,使用时才查询
  • lazy:false 加载时立即查询
    
  • load方法 在执行时不发送任何sql语句,返回一个对象,使用该对象时,才执行查询
Customer c = session.load(Customer.class,2l);

原理解释

在加载时,返回的是代理对象 代理对象会在使用对象属性时,根据关联的session查询数据库,加载数据
注意 使用懒加载时要确保,调用属性加载数据时,session是打开的 还没有关闭。否则会抛出异常

关联级别查询优化

关联级别查询优化

关联级别就是指对象的关联属性,分为两种:集合级别的关联。对象级别的关联

集合级别的关联策略

  • lazy:延迟加载
    lazy属性:延迟加载
    true:默认值 延迟加载
    false:立即加载
    extra:极其懒惰 与懒加载效果基本一致,如果只获得集合的size,只查询集合的size(count语句)
  • fetch:抓取策略
    fetch属性:决定加载策略,使用什么类型的sql语句加载集合数据
    select:单表查询加载
    join:使用多表查询加载集合 此种情况下 lazy属性失效 相当于立即加载 多表数据会直接全部加载
    subselect:使用子查询加载集合


    集合属性策略

对象属性级别的关联策略

主要作用于

  • lazy
    • false: 立即加载
    • proxy: 代理加载 由指定的代理决定加载策略
  • fetch
    • select: 使用单表查询
    • join: 使用多表查询


      关联属性策略

我们总结来说就是:fetch主要控制抓取关联对象的时候发送SQL语句的格式的lazy主要控制查询其关联对象的时候是否采用延迟加载的
为了提高效率:fetch的选择应该选择select lazy的取值应该选择true

批量抓取

批量抓取
 
        

你可能感兴趣的:(JAVAEE框架学习——Hibernate——事务 查询API应用、查询优化)