Hibernate学习之查询

本文详细介绍了Hibernate框架中的多种查询方式,包括OID检索、对象导航、HQL、QBC及原始SQL等,并深入探讨了HQL与QBC的具体用法,特别强调了面向对象的查询思维。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

##Hibernate框架学习之查询 ##




----------
例一:使用hibernate完成所有的员工的查询
----
**需求分析**


    1.完成所有员工的查询
    2.准备数据
        public class Emp {
            private Integer e_id;
            private String e_name;
            private String e_address;
            private String e_phone;
            private Dept dept;
            public Emp(){
                
            }
            public Emp(String e_name,String e_address){
                this.e_name=e_name;
                this.e_address=e_address;
            }
            @Override
            public String toString() {
                return "Emp [e_id=" + e_id + ", e_name=" + e_name + ", e_address=" + e_address + ", e_phone=" + e_phone
                        + "]";
            }
            :
            :
        }


        public class Dept {
            private Integer d_id;
            private String d_name;
            private Set<Emp> emps=new HashSet<Emp>();
            @Override
            public String toString() {
                return "Dept [d_id=" + d_id + ", d_name=" + d_name + ", emps=" + emps + "]";
            }
            :
            :
        }


        使用hibernate插入数据
        @Test
        public void test1(){
            Session session = HibernateUtils.getSession();
            Transaction tr= session.beginTransaction();
            //插入数据测试
            Dept dept1 = new Dept();
            Dept dept2 = new Dept();
            Dept dept3 = new Dept();
            Dept dept4 = new Dept();
            dept1.setD_name("研发部");
            dept2.setD_name("测试部");
            dept3.setD_name("运维部");
            dept4.setD_name("销售部");
            
            Emp emp1 = new Emp();
            Emp emp2 = new Emp();
            Emp emp3 = new Emp();
            Emp emp4 = new Emp();
            Emp emp6 = new Emp();
            emp1.setE_address("湖南");
            emp1.setE_name("小王");
            emp1.setDept(dept1);
            
            emp4.setE_address("广东");
            emp4.setE_name("小张");
            emp4.setDept(dept1);
            
            emp2.setE_address("湖北");
            emp2.setE_name("小李");
            emp2.setDept(dept2);
            
            emp3.setE_address("广东");
            emp3.setE_name("小邓");
            emp3.setDept(dept3);
            
            emp6.setE_address("广东");
            emp6.setE_name("小胡");
            
            
            session.save(emp1);
            session.save(emp2);
            session.save(emp3);
            session.save(emp4);
            session.save(emp6);
            session.save(dept4);
            tr.commit();
            session.close();
    }


-----


**hibernate插件的查询方式有下面几种**


    1.唯一标识OID的检索方式
        //session.get(对象.class,OID);
        Session session = HibernateUtils.getSession();
        Transaction tr= session.beginTransaction();
        Emp emp = session.get(Emp.class, 1);
        System.out.println(emp.getDept().getD_name());
        
        tr.commit();
        session.close();
        查询结果:研发部


    2.对象导航的检索方式
        /**
         * 对象导航的方式
         */
        @Test
        public void test3(){
            Session session = HibernateUtils.getSession();
            Transaction tr= session.beginTransaction();
            Dept dept = session.get(Dept.class, 1);
            System.out.println(dept.getEmps().size());
            tr.commit();
            session.close();
        }
        输出结果:2
        值得注意的是,在这里我们借助了OID的方式获得了部门对象,并没有得到员工对象,但是我们依然打印出了该部门下员工的人数


    3.HQL的检索方式
        HQL全称为:Hibernate Query Language 是hibernate框架自己的查询体系
    
    4.QBC的检索方式
        QBC全称为:Query By Criteria  //通过criteria接口的条件查询


    5.原始SQL检索
        hibernate支持原始SQL语句的查询,但是这与Hibernate的ORM思想不一致!


-------


**下面详细介绍下HQL检索与QBC检索**


-----
**HQL查询**
    
    1.HQL查询概述:
        HQL查询是一种面向对象的查询方式,符合ORM思想,底层采用映射的方式将HQL语句转为相应的SQL语句.
    2.与SQL语句的区别与联系
        底层依然是SQL语句,SQL操作的对象是字段和表,而HQL基于ORM思想操作的属性和对象
    3.查询语句演示
    
    3.1 基本查询格式
        @Test
        public void test4(){
            Session session = HibernateUtils.getSession();
            Transaction tr= session.beginTransaction();
            List<Emp> list = session.createQuery("from Emp").list();
            for (Emp emp : list) {
                System.out.print(emp.getE_name()+",");
            }
            tr.commit();
            session.close();
        }
        查询结果:小王,小李,小邓,小张,小胡,
        注意,这里使用的是类名
    3.2 HQL查询支持别名的方式
        List<Emp> list = session.createQuery("select e from Emp e").list();
    3.3 HQL排序查询
        List<Emp> list = session.createQuery("from Emp order by e_id desc").list();
        List<Emp> list = session.createQuery("from Emp order by e_id asc").list();
    3.4 HQL分页查询
            Query query = session.createQuery("from Emp");
            //得到Qeury对象,设置开始页
            query.setFirstResult(0);
            //设置每一页显示条数
            query.setMaxResults(3);
            List<Emp> list = query.list();
            for (Emp emp : list) {
                System.out.println(emp);
            }
            结果:
            Emp [e_id=1, e_name=小王, e_address=湖南, e_phone=null]
            Emp [e_id=2, e_name=小李, e_address=湖北, e_phone=null]
            Emp [e_id=3, e_name=小邓, e_address=广东, e_phone=null]
    3.5 HQL按条件查询
            Query query = session.createQuery("from Emp where e_name like ?");
            query.setParameter(0, "%王%");
            List<Emp> list = query.list();
            for (Emp emp : list) {
                System.out.println(emp);
            }
            结果是:Emp [e_id=1, e_name=小王, e_address=湖南, e_phone=null]
            注意,此时占位符是从0开始的
    3.6 HQL投影查询(其实就是选择几个想要的字段,无关字段不显示信息)
                与   SELECT e_name,e_address FROM e_emp;的效果是一致的
            @Test
            public void test9(){
                Session session = HibernateUtils.getSession();
                Transaction tr= session.beginTransaction();
                Query query = session.createQuery("select e.e_name,e.e_address from Emp e");
                List<Emp> list = query.list();
                for (Emp emp : list) {
                    System.out.println(emp);
                }
                tr.commit();
                session.close();
            }
            这样写会报错,因为返回的是一个Object类型的数组:java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to top.lingzhen.domain.Emp
            HIbernate给我们提供另外的方式即使是单个字段仍然可以封装为对象,但是需要提供必要的构造方法,并且无参构造方法仍需保留
            @Test
            public void test10(){
                Session session = HibernateUtils.getSession();
                Transaction tr= session.beginTransaction();
                Query query = session.createQuery("select new Emp(e.e_name,e.e_address) from Emp e");
                 List<Emp> list = query.list();
                for (Emp emp : list) {
                    System.out.println(emp.getE_name()+emp.getE_address());
                }
                tr.commit();
                session.close();
            }
            此时Emp实体类变化为
                public class Emp {
                    private Integer e_id;
                    private String e_name;
                    private String e_address;
                    private String e_phone;
                    private Dept dept;
                    public Emp(){
                        
                    }
                    public Emp(String e_name,String e_address){
                        this.e_name=e_name;
                        this.e_address=e_address;
                    }
                    :
                    :
                }
        3.7 HQL查询之聚合函数查询
            Query query = session.createQuery("select count(*) from Emp");
            List<Number> list = query.list();
            System.out.println(list.get(0).intValue());
            注意:此时返回的泛型类型,其他聚合函数查询与上面类似


---


**QBC**查询


    1.Queyr By Criteria查询是一种完全面向对象的查询
    2.QBC的简单格式
        List<Emp> list = session.createCriteria(Emp.class).list();
        for (Emp emp : list) {
            System.out.println(emp);
        }
        输出结果是
        Emp [e_id=1, e_name=小王, e_address=湖南, e_phone=null]
        Emp [e_id=2, e_name=小李, e_address=湖北, e_phone=null]
        Emp [e_id=3, e_name=小邓, e_address=广东, e_phone=null]
        Emp [e_id=4, e_name=小张, e_address=广东, e_phone=null]
        Emp [e_id=5, e_name=小胡, e_address=广东, e_phone=null]
    3.QBC的排序查询
        @Test
        public void test2(){
            Session session = HibernateUtils.getSession();
            Transaction tr= session.beginTransaction();
             Criteria criteria = session.createCriteria(Emp.class);
             List<Emp> list = criteria.addOrder(Order.desc("e_id")).list();
            for (Emp emp : list) {
                System.out.println(emp);
            }
        }
        Emp [e_id=5, e_name=小胡, e_address=广东, e_phone=null]
        Emp [e_id=4, e_name=小张, e_address=广东, e_phone=null]
        Emp [e_id=3, e_name=小邓, e_address=广东, e_phone=null]
        Emp [e_id=2, e_name=小李, e_address=湖北, e_phone=null]
        Emp [e_id=1, e_name=小王, e_address=湖南, e_phone=null]
        QBC查询都是通过调用方法实现查询的,查询条件就是对应的类属性
    4.QBC的分页查询
        @Test
        public void test3(){
            Session session = HibernateUtils.getSession();
            Transaction tr= session.beginTransaction();
            Criteria criteria = session.createCriteria(Emp.class);
            criteria.setFirstResult(0);
            criteria.setMaxResults(3);
            List<Emp> list = criteria.list();
            for (Emp emp : list) {
                System.out.println(emp);
            }
        }
        输出结果:
            Emp [e_id=1, e_name=小王, e_address=湖南, e_phone=null]
            Emp [e_id=2, e_name=小李, e_address=湖北, e_phone=null]
            Emp [e_id=3, e_name=小邓, e_address=广东, e_phone=null]
    5.QBC的条件查询
        @Test
        public void test4(){
            Session session = HibernateUtils.getSession();
            Transaction tr= session.beginTransaction();
            Criteria criteria = session.createCriteria(Emp.class);
            criteria.addOrder(Order.desc("e_id"));
            criteria.add(Restrictions.ge("e_id", 2));
            List<Emp> list = criteria.list();
            for (Emp emp : list) {
                System.out.println(emp);
            }
        }
        输出结果:
        Emp [e_id=5, e_name=小胡, e_address=广东, e_phone=null]
        Emp [e_id=4, e_name=小张, e_address=广东, e_phone=null]
        Emp [e_id=3, e_name=小邓, e_address=广东, e_phone=null]
        Emp [e_id=2, e_name=小李, e_address=湖北, e_phone=null]
        如果想查询多个条件,可以使用Restrictions.or(Restrictions.XX(),Restrictions.XX()...)或者Restrictions.add(...)
         Restrictions.eq           //相等
         Restrictions.gt           // 大于号
         Restrictions.ge           // 大于等于
         Restrictions.lt           // 小于
         Restrictions.le           // 小于等于
         Restrictions.between      // 在之间
         Restrictions.like         // 模糊查询
         Restrictions.in           // 范围
         Restrictions.and          // 并且
         Restrictions.or           // 或者
    6.QBC的聚合函数查询
        需要借助Projection来进行查询
        @Test
        public void test5(){
            Session session = HibernateUtils.getSession();
            Transaction tr= session.beginTransaction();
            Criteria criteria = session.createCriteria(Emp.class);
            List<Number> list = criteria.setProjection(Projections.rowCount()).list();
            
            System.out.println(list.get(0).intValue());
            /*criteria.setProjection(null);//如果要执行注释部分的代码,需要执行这句,破坏其格式
            List<Emp> list2 = criteria.addOrder(Order.desc("e_id")).list();
            for (Emp emp : list2) {
                System.out.println(emp);
            }*/
        }
                
----
**离线条件查询**


    1.离线条件查询的意义:可以在WEB层不借助session获得查询对象,进行查询条件的拼接,最后执行把离线查询对象传到持久层就可以了,简化开发,不过在执行的适合还是需要session对象。
    @Test
    public void test6(){
        Session session = HibernateUtils.getSession();
        Transaction tr= session.beginTransaction();
        DetachedCriteria forClass = DetachedCriteria.forClass(Emp.class);
        DetachedCriteria add = forClass.add(Restrictions.ge("e_id",3));
        //执行时仍需要session
        List<Emp> list = add.getExecutableCriteria(session).list();
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }
    执行结果:
        Emp [e_id=3, e_name=小邓, e_address=广东, e_phone=null]
        Emp [e_id=4, e_name=小张, e_address=广东, e_phone=null]
        Emp [e_id=5, e_name=小胡, e_address=广东, e_phone=null]


-----
**HQL的多表查询**
    
    1.普通内连接
    @Test
    public void test6(){
        Session session = HibernateUtils.getSession();
        Transaction tr= session.beginTransaction();
        //注意返回结果
        List<Object[]> list=session.createQuery("from Emp e inner join e.dept").list();
        for (Object[] objects : list) {
            System.out.println(Arrays.toString(objects));
        }
    }
    2.使用fetch关键字的迫切内连接,能将查询结果封装为对象
        @Test
        public void test7(){
            Session session = HibernateUtils.getSession();
            Transaction tr= session.beginTransaction();
            List<Emp> list=session.createQuery("from Emp e inner join fetch e.dept").list();
            for (Emp emp : list) {
                System.out.println(emp+"=="+emp.getDept().getD_name());
            }
        }
        查询结果:
            Emp [e_id=1, e_name=小王, e_address=湖南, e_phone=null]==研发部
            Emp [e_id=4, e_name=小张, e_address=广东, e_phone=null]==研发部
            Emp [e_id=2, e_name=小李, e_address=湖北, e_phone=null]==测试部
            Emp [e_id=3, e_name=小邓, e_address=广东, e_phone=null]==运维部
    3.左外连接,右外连接查询与上面相似
        left join fetch   //迫切左外连接
        right join fetch  //迫切右外连接
        @Test
        public void test8(){
            Session session = HibernateUtils.getSession();
            Transaction tr= session.beginTransaction();
            List<Emp> list=session.createQuery("from Emp e left join fetch e.dept").list();
            for (Emp emp : list) {
                System.out.println(emp);
            }
        }
        查询结果:
            Emp [e_id=1, e_name=小王, e_address=湖南, e_phone=null]
            Emp [e_id=2, e_name=小李, e_address=湖北, e_phone=null]
            Emp [e_id=3, e_name=小邓, e_address=广东, e_phone=null]
            Emp [e_id=4, e_name=小张, e_address=广东, e_phone=null]
            Emp [e_id=5, e_name=小胡, e_address=广东, e_phone=null]
            注意,不同的左右表查询最后的结果是不一致的,封装不上就为null


---




            
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值