zoukankan      html  css  js  c++  java
  • Hibernate:查询


    本文内容

    • OID查询
    • 对象导航查询
    • HQL查询
    • QBC查询
    • SQL查询

    首发日期:2018-07-31


    hibernate的查询方式:

    hibernate有很多查询方式

    • OID查询
    • 对象导航查询:
    • HQL查询:
    • QBC查询:
    • SQL查询:

    OID查询:

    OID查询:基于唯一标识属性(主键)来查询

    • 使用方法:session.get(持久类.class,主键值)或session.load(持久类.class,主键值)
    public void test1() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Person p1 = session.get(Person.class, 1L);//因为我用的是Long,所以这里给个1L
            Person p2 = session.load(Person.class, 2L);//不会立即发生sql语句
            System.out.println(p1);
            System.out.println(p2);//这里才发送p2的查询
        }

    get和load的区别:

    load是延迟加载的,意思是当调用load的时候,并不立即发送SQL语句,只有当使用了这个对象的时候才去发送SQL语句。

    而且,get对于不存在的对象的查询返回的是null,load会报错。


    对象导航查询

    对象导航查询:利用对象之间的关系来获取【前提--对象之间建立了关系,比如给某个学生选择了班级,那么就可以通过这个学生来查询到班级,而无法通过这个学生查询到没有跟他绑定的班级】

    • 使用方法:利用对象的关系【参照例子帮助了解,以一对多关系为例。】
    public void test2() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Student student = session.get(Student.class, 1L);
            Grade grade = student.getGrade();
            System.out.println(grade);
            Grade grade2 = session.get(Grade.class, 1L);
            for (Student s : grade2.getStudents()) {
                System.out.println(s);
            }
            
        }

    HQL查询:

    HQL是hibernate版本的SQL语句,HQL与SQL相像,不过它的表名变成了类名,字段名变成了属性名。

    • 执行HQL查询:Query query = session.createQuery(HQL语句);
    • 获取结果:query.list()【获取结果集】、query.unique()【如果只查单行单列数据,用这个】

    查询所有:

    HQL中的"from 类名"相当于SQL中的“select * from 表名”

    public void test3() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Query query = session.createQuery("from Student ");
            List<Student> list = query.list();
            for(Student s :list) {
                System.out.println(s);
            }
            
        }

    别名查询

    HQL中也给可以给类名指定一个别名。

    public void test4() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Query query = session.createQuery("select s from Student s ");
            List<Student> list = query.list();
            for(Student s :list) {
                System.out.println(s);
            }

    排序查询:

    HQL的排序查询也类似于SQL,不过它的排序条件是类的属性名

    public void test5() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Query query = session.createQuery("from Student order by id desc");
            List<Student> list = query.list();
            for(Student s :list) {
                System.out.println(s);
            }

    条件查询:

    HQL的条件查询也类似于SQL,不过它的条件中字段名是类的属性名

    条件都是跟在from 类名后面,不过设置值的方法有三种:

    1. 直接设置
    2. 使用?占位,然后使用setParameter(下标,值)设置【不过好像一些版本不再支持这个】
    3. 使用:XXX占位,然后是setParameter(XXX,值)设置
    public void test6() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            //方式1
    //        Query query = session.createQuery("from Student where id = 1");
            //方式2
    //        Query query = session.createQuery("from Student where name = ?");
    //        query.setParameter(0, "李白");
            //方式3
            Query query = session.createQuery("from Student where id = :aaa");
            query.setParameter("aaa", 1L);
            List<Student> list = query.list();
            for(Student s :list) {
                System.out.println(s);
            }
        }

    投影查询:

    投影查询就是查询对象的某个或某些属性,这个用法与SQL基本相同。不过这个时候使用query.list得出的结果是Object类型的。

    public void test7() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Query query = session.createQuery("select name from Student");
            List<Object> list = query.list();
            //如果你的Student有合适参数的构造函数,那么你可以这样用,这会帮你封装到对象中,返回的也是Student对象
    //        Query query = session.createQuery("select new Student(id,name) from Student");
    //        List<Student> list = query.list();
            
            for(Object s :list) {
                System.out.println(s);
            }
        }

    分页查询:

    HQL分页查询的核心函数是setMaxResult(一页显示的条数),setFirstResult(第一条记录的索引值)

    public void test8() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Query query = session.createQuery("from Student");
            query.setMaxResults(3);
            query.setFirstResult(0);
            List<Student> list = query.list();
            
            for(Student s :list) {
                System.out.println(s);
            }
        }

    分组统计查询:

    HQL分组统计查询与SQL的分组统计查询的语法相类似。

    public void test9() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Query query = session.createQuery("select count(*) from Student group by grade");//这样得出的是Object[]类型的数据
            List<Object > list = query.list();
            
            for(Object o :list) {
                System.out.println(o);
            }
        }

    多表查询:

    HQL的多表查询有几个不同

    1.它不是使用表名,它使用持久类的类名

    2.它可以使用映射外键,比如:from Student s inner join Grade g on s.grade=g.id

    3.使用持久类的类名之后,它可以直接利用关联关系来进行连接,例如:from Student s inner join s.grade

    public void test10() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            //内连接
    //        Query query = session.createQuery("from Student s inner join s.grade");//这样得出的是Object[]类型的数据
    //        Query query = session.createQuery("from Student s inner join Grade g on s.grade=g.id");//这样得出的是Object[]类型的数据
    //        List<Object[] > list = query.list();
    //        for(Object[] o :list) {
    //            System.out.println(Arrays.toString(o));
    //        }
            //左外连接
    //        Query query = session.createQuery("from Student s left  join s.grade");//这样得出的是Object[]类型的数据
    //        Query query = session.createQuery("from Student s left  join Grade g on s.grade=g.id");//这样得出的是Object[]类型的数据
    //        List<Object[] > list = query.list();
    //        for(Object[] o :list) {
    //            System.out.println(Arrays.toString(o));
    //        }
            //右外连接差不多,这里不讲了
        }

    多表查询中有两个特殊的连接:迫切内连接和迫切左外连接。当利用关联关系来连接的时候,在后面那个关联之前加个fetch,效果是把后面那个关联持久类的内容封装到前面那个类的实体中。

    比如:

    image

    补充:

    • 很多时候都要依靠query.list()来获取结果,那么怎么判断返回的结果是什么类型的呢?
      • 查询结果是单列的时候,是Object
      • 查询结果是一个个持久类对象的时候,返回的是持久类
      • 查询结果是多列数据,而且不全是某个持久类的所有数据的时候,返回的是Object[]


    QBC查询

    • QBC(Query By Criteria)查询是面向对象的查询
    • 使用方法:Criteria criteria = session.createCriteria(持久类.class);
    • 获取结果: criteria.list();

    查询所有:

    public void test1() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Criteria criteria = session.createCriteria(Student.class);
            List<Student> list = criteria.list();
            for(Student s:list) {
                System.out.println(s);
            }

    排序查询:

    在查询所有的基础上,调用criteria.addOrder()来进行排序,参数Order.desc(根据哪个字段排序)、Order.asc(根据哪个字段排序)

    public void test2() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Criteria criteria = session.createCriteria(Student.class);
            criteria.addOrder(Order.desc("id"));
            List<Student> list = criteria.list();
            for(Student s:list) {
                System.out.println(s);
            }
            
        }

    条件查询:

    在查询所有的基础上,调用criteria.add()来增加条件,参数是Restrictions.xxx

    Restrictions.xxx常用的有

    Restrictions.eq(属性名,值):相当于条件 where 字段名 =值

    Restrictions.gt(属性名,值):相当于条件 where 字段名 >值

    Restrictions.ge(属性名,值):相当于条件 where 字段名 >=值

    Restrictions.lt(属性名,值):相当于条件 where 字段名 <值

    Restrictions.in(属性名,集合):相当于条件 where 字段名 in 值

    默认情况下,增加的每一个都是与的条件,要想添加或的条件,要使用Restrictions.or(多个Restrictions.xxxx),这样里面的条件都是或的了。

    public void test4() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Criteria criteria = session.createCriteria(Student.class);
            criteria.add(Restrictions.eq("name", "李白"));
            List<Student> list = criteria.list();
            for(Student s:list) {
                System.out.println(s);
            }
            
        }

    分页查询:

    criteria调用setFirstResult(第一条记录的索引),调用setMaxResults(一页显示的数量)来进行分页。

    public void test3() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Criteria criteria = session.createCriteria(Student.class);
            criteria.setFirstResult(0);//第一条记录的索引
            criteria.setMaxResults(3);//一页显示多少
            List<Student> list = criteria.list();
            for(Student s:list) {
                System.out.println(s);
            }
            
        }

    统计查询:

    criteria调用setProjection(Projections.XXX)来进行统计查询

    Projections.XXX有

    image

    public void test5() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            Criteria criteria = session.createCriteria(Student.class);
            criteria.setProjection(Projections.rowCount());
            Long count = (Long) criteria.uniqueResult();
            System.out.println(count);
            
        }

    补充:

    • QBC中还有个离线条件查询DetachedCriteria,这里暂时不讲,以后有空再加上。


    SQL查询

    SQL查询就是直接使用SQL语句来查询

    进行查询:SQLQuery sqlQuery = session.createSQLQuery(SQL语句)

    获取结果:sqlQuery.list()

    相信你是已经学过SQL语句的。所以这里就给出怎么用,不详细介绍各种查询了。

    直接使用的时候,返回结果是一个个Object[]

    public void test1() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            //发现提示用法过期了,不过还是介绍一下
            SQLQuery sqlQuery = session.createSQLQuery("select * from student");
            List<Object[] > list = sqlQuery.list();
            for(Object[] o:list) {
                System.out.println(Arrays.toString(o));
            }
        }
    但可以使用sqlQuery.addEntity(持久类.class)来把数据封装到对象中;
    public void test2() {
            Configuration cfg = new Configuration().configure();
            SessionFactory factory = cfg.buildSessionFactory();
            Session session = factory.openSession();
            //发现提示用法过期了,不过还是介绍一下
            SQLQuery sqlQuery = session.createSQLQuery("select * from student");
            sqlQuery.addEntity(Student.class);
            List<Student > list = sqlQuery.list();
            for(Student s:list) {
                System.out.println(s);
            }
        }

  • 相关阅读:
    QtCreator无法编辑源文件
    【Newtonsoft.Json】自己实现JsonConverter ,精简返回的数据结果
    Ghostscript 将PDF文件转换成PNG图片 问题一二
    Nginx--面试基础必会
    Nginx日志配置
    Nginx缓存原理及机制
    Nginx限流
    Nginx 实现 Rewrite 跳转
    Nginx正确配置Location
    渐进深入理解Nginx
  • 原文地址:https://www.cnblogs.com/progor/p/9393641.html
Copyright © 2011-2022 走看看