美文网首页JAVAEE
JAVAEE框架学习——Hibernate——事务 查询API应

JAVAEE框架学习——Hibernate——事务 查询API应

作者: So_ProbuING | 来源:发表于2018-05-15 18:33 被阅读3次

    Hibernate 事物

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

    Hibernate中的事物管理

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


    事物隔离级别
    • 在hibernate.cfg.xml文件中的<session-factory>标签元素中进行配置
     <!--配置数据库隔离级别
                0001 1 读未提交
                0010 2 读已提交
                0100 4 可重复读
                1000 8 串行
            -->
            <property name="hibernate.connection.isolation ">4</property>
    

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

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

    • 在dao层操作数据库的时候需要用到session对象,在service控制事物也是使用session对象完成,所以我们要确保dao层和service层使用的是同一个session对象
      注意1:调用getCurrentSession方法必须配合主配置中的一段配置
       <!--指定session与当前线程绑定-->
            <property name="current_session_context_class">thread</property>
    

    注意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<Customer> 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<Customer> 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<Customer> 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<Customer> 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<Customer> 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<Customer> 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<Customer> 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<Customer> 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<Customer> list = query.list();
            //查询结果 未指定封装对象
            List<Object[]> 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<Customer> 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<Customer> list = query.list();
            //查询结果 未指定封装对象
    //        List<Object[]> 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<Customer> list = c.list();
            System.out.println(list);
        }
    

    查询优化

    类级别查询优化

    延迟加载

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

    • lazy:true 加载时,不查询,使用时才查询
    • lazy:false 加载时立即查询
        <class name="Customer" table="cst_customer" lazy="true">
    
    • 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:使用子查询加载集合


      集合属性策略

    对象属性级别的关联策略

    主要作用于<many-to-one>

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


        关联属性策略

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

    批量抓取

    批量抓取
     <!--
                batch-size:抓取集合的数量为3
            -->
            <set name="linkMens" inverse="true" batch-size="3">
    

    相关文章

      网友评论

        本文标题:JAVAEE框架学习——Hibernate——事务 查询API应

        本文链接:https://www.haomeiwen.com/subject/qabedftx.html