zoukankan      html  css  js  c++  java
  • HQL(Hibernate Query Language)详解

    一、HQL介绍

    面向对象的查询语言,与SQL不同,HQL中的对象是区分大小写的(除了JAVA类和属性其他部分不区分大小写);HQL中查的是对象而不是表,并且支持多态;HQL主要通过Query来操作,Query的创建方式:
    Query q = session.createQuery(hql);
    from Person
    from User user where user.name=:name
    from User user where user.name=:name and user.birthday < :birthday
     
    二、criteria
    Criteria是一种比HQL更面向对象的查询方式;Criteria的创建方式:
    Criteria crit = session.createCriteria(DomainClass.class);
    简单属性条件如:
    criteria.add(Restrictions.eq(propertyName,value)),
    criteria.add(Restrictions.eqProperty(propertyName,otherPropertyName))
     
    三、表结构设计
    学生选课系统,三张表
    设计表的时候,应当每张表有一个主键,而且该主键最好不含业务逻辑
    使用hibernate工具,自动生成domain对象和映射文件,如果表主外键的关系,则应当先映射主表,再映射从表
    create sequence stucourse_seq 
    start with 1 
    increment by 1 
    nocache 
    nocycle
    nomaxvalue
    minvalue 1
    /
     
    --建立学生表
    create table student
    (sid number primary key , --这是学生的学号
    sname varchar2(45) not null, --学生姓名
    ssex char(2) not null,--性别
    sdept varchar2(10) not null, --所在系
    sage number(3) ,--年龄
    saddress varchar2(45) --住址
    )
    --学生表中的数据
    insert into student values(20040001,'林青霞','F','计算机系',22,'上海');
    insert into student values(20040002,'刘德华','M','外语系',23,'南京');
    insert into student values(20050003,'成龙','M','化学系',21,'山东');
    insert into student values(20050004,'林可欣','F','计算机系',22,'北京');
    insert into student values(20050005,'周华健','M','生物系',24,'山东');
    insert into student values(20050006,'周润发','M','数学系',20,'湖北');
    --建立课程表
    create table course
    (
    cid number primary key ,--这是课程号
    cname varchar2(50) not null,--课程名
    ccredit number(3) --课程学分
    )
    insert into course values(11,'java编程',6);
    insert into course values(21,'c++课程',4);
    insert into course values(31,'oracle',3);
    insert into course values(41,'javaEE',100);
    insert into course values(51,'linux',1);
    --建立选课表
    create table studCourse
    (
    stuCourseId number primary key ,--这是一个自增的,表示一次选课
    sid number references student(sid),--学生号
    cid number references course(cid),--课程号
    grade number not null--成绩
    )
    --初始化数据
    insert into studCourse values(stucourse_seq.nextval,20040001,11,90);
    insert into studCourse values(stucourse_seq.nextval,20040001,21,19);
    insert into studCourse values(stucourse_seq.nextval,20050003,21,45);
    insert into studCourse values(stucourse_seq.nextval,20050004,41,99);
    insert into studCourse values(stucourse_seq.nextval,20050006,11,39);
     
    四、HQL语法详解
    1、检索所有的学生
    List<Student> list = session.createQuery("from Student").list();
    //1.使用for取出
    for(Student s:list){
        System.out.println(s.getSname()+" "+s.getSaddress());
        //查看所选的课程
        if(s.getStudcourses().size()==0){
               System.out.println(s.getSname()+"没有选课");
        }else{
            Set<Studcourse> set = s.getStudcourses();
            for(Studcourse sc : set){
                System.out.println(s.getSname()+"选了"+sc.getCourse().getCname());
            }
        }
    }
    //2.使用iterator取出
    Iterator<Student> iterator = list.iterator();
    while(iterator.hasNext){
        Student s = iterator.next();
        System.out.println(s.getSname()+" "+s.getSage());
    }

    2、检索学生的名字和所在系

    List list = session.createQuery("select sname,sdept from Student").list();
    for(int i=0;i<list.size();i++){
        Object[] objs = (Object[]) list.get(i);
        System.out.println(objs[0].toString()+" "+objs[1].toString());
    }
    //使用iterator
    Iterator it = list.iterator();
    while(it.hasNext()){
        Object[] objs = (Object[]) it.next();
        System.out.println(objs[0].toString()+" "+objs[1].toString());
    }

    3、uniqueResult

    如果检索一个对象,明确知道最多只有一个对象,则建议使用该方法

    Student s = (Student) session.createQuery("from Student where id='20050003'").uniqueResult();
    System.out.println(s.getSname());

    4、过滤重复值,显示所有学生的性别和年龄

    List list = session.createQuery("select distinct sage,ssex from Student").list();
    for(int i=0;i<list.size();i++){
        Object[] objs = (Object[]) list.get(i);
        System.out.println(objs[0].toString()+" "+objs[1].toString());
    }

    5、计算年龄在20-22之间的学生

    List list = 
    session.createQuery("select distinct sage,ssex,sname from Student where sage between 20 and 22")
    .list();
    for(int i=0;i<list.size();i++){ Object[] objs = (Object[]) list.get(i); System.out.println(objs[0].toString()+" "+objs[1].toString()+" "+objs[2].toString()); }

    6、查询计算机系和外语系的学生信息

    List list = 
    session.createQuery("select sage,ssex,sname from Student where sdept in ('计算机系','外语系')").list(); for(int i=0;i<list.size();i++){ Object[] objs = (Object[]) list.get(i); System.out.println(objs[0].toString()+" "+objs[1].toString()+" "+objs[2].toString()); }

    7、显示各个系的学生的平均年龄

    List list = session.createQuery("select avg(sage),sdept from Student group by sdept").list();
    for(int i=0;i<list.size();i++){
        Object[] objs = (Object[]) list.get(i);
        System.out.println(objs[0].toString()+" "+objs[1].toString());
    }

    8、having的使用

    对分组查询后的结果,进行筛选:比如请显示人数大于3的名称

    //a.查询各个系分别有多少学生
    List list = session.createQuery("select count(*),sdept from Student group by sdept having count(*)>3").list();
    for(int i=0;i<list.size();i++){
        Object[] objs = (Object[]) list.get(i);
        System.out.println(objs[0].toString()+" "+objs[1].toString());
    }

    9、查询女生少于200人的系

    //a.查询各个系的女生有多少个
    List list = session.createQuery("select count(*),sdept from Student where ssex='F' group by sdept").list();
    for(int i=0;i<list.size();i++){
        Object[] objs = (Object[]) list.get(i);
        System.out.println(objs[0].toString()+" "+objs[1].toString());
    }

    10、查询计算机系共多少人

    //如果返回的是一列数据
    List list = session.createQuery("select count(*) from Student where sdept='计算机系' group by sdept").list();
    for(int i=0;i<list.size();i++){
        Object objs = (Object) list.get(i);
        System.out.println(objs.toString()+" "+objs.toString());
    }

    11、查询总学分是多少

    List<Object[]> list =session.createQuery("select sum(grade) from Studcourse").list();
    for(Object obj:list){
        System.out.println(obj.toString());
    }

    12、查询选修11号课程的最高分和最低分

    List<Object[]> list =session.createQuery("select 11,max(grade),min(grade) from Studcourse where course.cid=11").list();
    for(Objec[]t obj:list){
        System.out.println(obj[0].toString()+" "+obj[1].toString()+" "+obj[2].toString());
    }

    13、显示各科考试不及格学生的名字(Student-student),科目(Course-course) 和分数(Studcourse-studcourse)

    List<Object[]> list =session.createQuery("select student.sname,course.cname,grade from Studcourse where grade<60").list();
    for(Objec[]t obj:list){
        System.out.println(obj[0].toString()+" "+obj[1].toString()+" "+obj[2].toString());
    }

    14、计算各个科目不及格的学生数量

    List<Object[]> list =
    session.createQuery("select count(*),student.sdept from Studcourse where grade<60 group by student.sdept")
    .list();
    for(Objec[]t obj:list){ System.out.println(obj[0].toString()+" "+obj[1].toString()+" "+obj[2].toString()); }

    15、子查询

    显示所有选择了21号课程的学生信息

    String hql = "select student.sname,student.sdept from Studcourse where course.cid=?";
    String parameters[] = {"21"};
    List<Object[]> list = HibernateUtil.executeQuery(hql,parameters);
    for(Object[] s:list){
        System.out.println(s[0].toString()+" "+s[1].toString());
    }
    或者
    //要关闭懒加载
    String hql = "from Studcourse where course.cid=21";
    List<Studcourse> list = HibernateUtil.executeQuery(hql,null);
    for(Studcourse sc:list){
           System.out.println(sc.getGrade()+sc.getStudent().getSname());
    }

    五、分页

    请按照学生的年龄从小到大,取出第一个到第三个学生

    List<Student> list = 
    session.createQuery("from Student order by sage").setFirstResult(0).setMaxResults(3).list(); for(Student s:list){ System.out.println(s.getSname+" "+s.getSage()); }

    分页函数

    private static void showResultByPage(int pageSize){
        //设置分页的变量
        int pageNow = 1;
        int pageCount = 1;
        int rowCount = 1;
        
        Session session =  null;
        Transaction tx = null;
        try{
            session=HibernateUtil.getCurrentSession();
            tx = session.beginTransaction();
            rowCount = Integer.parseInt(session.createQuery("select count(*) from Student").uniqueResult().toString());
            pageCount = (rowCount-1)/pageSize+1;
    
            //循环的显示每页的信息
            for(int i=1;i<=pageCount;i++){
                System.out.println("******************"+i+"页***********************");
                List<Student> = session.createQuery("from Student").setFirstResult((i-1)*pageSize).setMaxResults(pageSize).list();
                for(Student s:list){
                    System.out.println(s.getSname()+" "+s.getSdept());
                }
            }
            tx.commit();
        }catch(Exception e){
            e.printStackTrace();
            if(tx!=null){
                 tx.rollback();
            }
            throw new RuntimeException(e.getMessage());
        }finally{
            if(session!=null && session.isOpen()){
                session.close();
            }
        }
    }
     六、参数绑定
     使用绑定参数的好处:
    1、可读性好
    2、性能提高
    3、防止sql注入
    List<Student> list = session.createQuery("from Student where sdept=:a1 and sage>:sage")
    .setString("a1","计算机系").setString("sage","2")
    .list();
    
    //使用问号,代表要注入的参数 List
    <Student> list = session.createQuery("from Student where sdept=? and sage>?") .setString(0,"计算机系").setString(1,"2") .list();
    //分解参数注入步骤,利于循环封装 Query query
    = session.createQuery("from Student where sdept=? and sage>?"); query.setString(0,"计算机系"); query.setString(1,"2"); List<Student> list = query.list(); for(int i=0;i<list.size();i++){ Student s = list.get(i); System.out.println(s.getSname()+" "+s.getSage()); }
    七、在映射文件中获取hql语句
    可以从映射文件中得到hql,执行查询语句,这样可以更加灵活,在某些情况下,可以考虑使用:
    比如在Student.hbm.xml中
    <query name="myquerytest">
        <![CDATA[select sname,ssex from Student where sage>22]]>
    </query>

    如何使用:

    List list = session.getNamedQuery("myquerytest").list();
    System.out.println(list.size());
    Iteraror it = list.iterator();
    while(it.hasNext()){
        Object obj[] = (Object[])it.next();
        System.out.println("n="+obj[0]);
    }
    八、criteria查询
    查询年龄大于10岁的学生
    Session s = HibernateUtil.getCurrentSession();
    Transaction tx = s.beginTransaction();
    Criteria cri = s.createCriteria(Student.class);
    //添加检索条件
    cri.add(Restrictions.gt("sage",new Long(10)));
    List<Student> list = cri.list();
    for(Student s1 : list){
        System.out.println(s1.getSname());
    }
    tx.commit();
     九、hibernate对象的三种关系
    1、one-to-one:省份证<--->人
    2、one-to-many:部门<--->员工
    3、many-to-one:员工<--->部门
    4、many-to-many:学生<--->老师
    在实际开发中,如果出现了many-to-many关系,我们应该将其转换成两个one-to-many或者many-to-one,这样好控制,同时不会出现冗余。
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    转--- 一些概念不错的理解
    python 生产者 --- 消费者
    python GUI 之 tkinter
    读DataSnap源代码(二)
    读DataSnap源代码(一)
    FireDAC探索 (二)
    FireDAC内部初探
    C++Builder XE7 中“匿名”方法实现
    DelphiXE7 Datasnap TDSClientCallbackChannelManager内部实现初探
    C++ Builder使用VC DLL
  • 原文地址:https://www.cnblogs.com/jingyunyb/p/3545560.html
Copyright © 2011-2022 走看看