zoukankan      html  css  js  c++  java
  • 027 hibernate查询语言(HQL)

    • 概述:数据查询与检索是Hibernate中的一个亮点,相对其他ORM实现而言,Hibernate提供了灵活多样的查询机制。
    • 标准化对象查询(Criteria Query):以对象的方式进行查询,将查询语句封闭为对象操作。优点:可主动性好,符合Java程序员的编码习惯。缺点:不够成熟,不支持投影
    • (projection)或统计函数(aggregation)

    n   例:查询用户名以“J”开头的所有用户

    Criteria c = session.createCreateria(User.class);

    c.add(Expression.like(“name”,”J%”));

    List users = c.list();

    • Hibernate语句查询(Hibernate Query Language,HQL)它是完全面向对象的查询语句,查询功能非常强大,具备多态、关联待特性。
    • Native SQL Queries(原生SQL查询)直接使用标准SQL语言或跟特定数据库相关的SQL进行查询。
    • Ø  注:除了Java类与属性的名称外,查询语句对大小写并不敏感。 所以 SeLeCTsELEct 以及 SELECT 是相同的,但是 org.hibernate.eg.FOO 并不等价于 org.hibernate.eg.Foo 并且 foo.barSet 也不等价于 foo.BARSET
    • HQL用面向对象的方式生成SQL

    n   以类和属性来代替表和数据列

    n   支持多态

    n   支持各种关联

    n   减少了SQL的冗余

    • HQL支持所有的关系数据库操作

    n   连接(joins,包括inner/outer/full joins),笛卡尔积(Cartesian products)

    n   投影(projection)

    n   聚合(Aggregation,max,avg)和分组(group)

    n   排序(ordering)

    n   子查询(subqueries)

    n   SQL函数(SQL function calls)

    HQL语言是一套中立语言:它与任何数据库都没有关系,通过hibernate的方言自动的把HQL语言翻译成各种数据库语言

    027-1 HQL简单例子

    例一:查询用户名以“J”开头的所有用户:

    Query query = session.createSQLQuery("from User user where user.name like 'J%'");

            List users = query.list();

    注:User是指User实体类 并重新起别名为user

    user.name:表示实体类的属性

    HQL中不使用表名,字段名,全部使用实体类、实体类的属性

    例二:复杂例子:从User和Group中查找属于“admin”组的所有用户

    Query query = session.createQuery("from User user where user.group.name='admin'");

        注:user.group.name:表示实体类User中组(group)中的名称(name)

    传统的SQL

    select user.userId as userId, user.name as name, user.groupId as groupid, user.idCardId as IdCardId from TBL_USER USER, TBL_GROUP group where (group.groupName=’admin’ and user.groupid=groupid.groupid)

    语法:HQL语言中的关键字不区分大小写,但是属性和类名区分大小写,from后面跟的是类名,不是表名。

     

    HQL演示环境

    学生与班级的关联映射

    Classes实体类:

    public class Classes {
    
        private int id;
        private String name;   
        //一对多通常使用Set来映射,Set是不可重复内容。
        //注意使用Set这个接口,不要使用HashSet,因为hibernate有延迟加载,
        private Set students;
    
     
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Set getStudents() {
            return students;
        }
        public void setStudents(Set students) {
            this.students = students;
        }
    
    }

    Student实体类:

    public class Student {
    
        private int id;
        private String name;   
        private Date createTime;
        private Classes classes;   
    
        public Date getCreateTime() {
           return createTime;
        }
    
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
        public int getId() {
            return id;
        }
    
       public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Classes getClasses() {
            return classes;
        }
        public void setClasses(Classes classes) {
            this.classes = classes;
        }
    
    }

    Classes实体类的映射文件:

    <hibernate-mapping>
        <class name="com.wjt276.hibernate.Classes" table="t_classes">
            <id name="id" column="id">
                <generator class="native"/>
           </id>
           <property name="name" column="name"/>    
            <!--
    
                <set>标签 映射一对多(映射set集合),name="属性集合名称"
                然后在用<key>标签,在多的一端加入一个外键(column属性指定列名称)指向一的一端
                再采用<one-to-many>标签说明一对多,还指定<set>标签中name="students"这个集合中的类型
                要使用完整的类路径(例如:class="com.wjt276.hibernate.Student")
                inverse="false":一的一端维护关系失效(反转) :false:可以从一的一端维护关系(默认);true:从一的一端维护关系失效
             -->
            <set name="students" inverse="true">
                <key column="classesid"/>
                <one-to-many class="com.wjt276.hibernate.Student"/>
            </set>
        </class>
    
    </hibernate-mapping>

    Student实体类映射文件:

    <hibernate-mapping>
        <class name="com.wjt276.hibernate.Student" table="t_student">
            <id name="id" column="id">
                <generator class="native"/>
            </id>
            <property name="name" column="name"/>
            <property name="createTime"/>
            <many-to-one name="classes" column="classesid"/>
        </class>
    </hibernate-mapping>

    初始化演示需要的数据:

    public class InitData {
    
        public static void main(String[] args) {
            Session session = HibernateUtils.getSession();
            try {
                session.beginTransaction();
                for (int i = 0; i < 10; i++) {
                    Classes classes = new Classes();
                    classes.setName("班级" + i);
                   session.save(classes);
                    for (int j = 0; j < 10; j++) {
                        Student student = new Student();
                        student.setName("班级" + i + "的学生" + j);
                        student
                                .setCreateTime(randomDate("2008-01-01",
                                        "2008-03-01"));
                        // 在内存中建立由student指向classes的引用
                        student.setClasses(classes);
                        session.save(student);
                    }
                }
                for (int i = 0; i < 5; i++) {
                    Classes classes = new Classes();
                    classes.setName("无学生班级" + i);
                    session.save(classes);
                }
                for (int i = 0; i < 10; i++) {
                    Student student = new Student();
                    student.setName("无业游民" + i);
                    session.save(student);
                }
    
     
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            } finally {
                HibernateUtils.closeSession(session);
            }
        }
    
        /**
         * 获取随机日期
         * @param beginDate       起始日期,格式为:yyyy-MM-dd
         * @param endDate    结束日期,格式为:yyyy-MM-dd
         */
    
        private static Date randomDate(String beginDate, String endDate) {
            try {
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    
                Date start = format.parse(beginDate);
                Date end = format.parse(endDate);
    
                if (start.getTime() >= end.getTime()) {
                    return null;
                }
                long date = random(start.getTime(), end.getTime());
                return new Date(date);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
     
    
        private static long random(long begin, long end) {
            long rtn = begin + (long) (Math.random() * (end - begin));
            if (rtn == begin || rtn == end) {
                return random(begin, end);
            }
            return rtn;
        }
    
    }

    org.hibernate.Query  Session.createQuery返回执行HQL查询的Query实例。

    Session.createSQLQuery返回执行本地SQL查询的Query实例。

     

    • List org.hibernate.Query.list():返回结果集列表。注:不同的HQL语句,返回不同的结果集列表

    1.简单属性的查询

    01 单一属性查询

    查询:所有学生称名:

    query.list():返回是单一属性的集合,

    元素类型和实体类中相应的属性类型一致,就是说List的类型取决于实体类属性的类型

    session = HibernateUtils.getSession();
    
                tx = session.beginTransaction();
        //单一属性查询,query.list()返回是单一属性的集合,元素类型和实体类中相应的属性类型一致,就是说List
        //的类型取决于实体类属性的类型
    
                List student = session.createQuery("select name from Student").list();
             
                for (Iterator iter = student.iterator(); iter.hasNext();)
                    String name = (String)iter.next();//实体类Student的属性name类型为String
                    System.out.println(name);
                }
                tx.commit();

    注:select name from Student

        Student:不是数据库中的表,而是Student实体类,所以需要区分大小写

        name:不是表中的字段名,而是Student实体类中的属性,所以需要区分大小写

    02 多个属性查询

    查询:所有学生的ID、姓名

    Query.list():返回结果集合元素是对象数组

    数组元素的类型和对应的属性在实体类中的类型一致

                数组的长度取决与select中属性的个数

                数组中元素的顺序,也取决与select中属性的顺序

    session = HibernateUtils.getSession();
    
                tx = session.beginTransaction();         
                //查询多个属性,其返回结果集合元素是对象数组
                //数组元素的类型和对应的属性在实体类中的类型一致
                //数组的长度取决与select中属性的个数
                //数组中元素的顺序,也取决与select中属性的顺序
                List student = session.createQuery("select id, name from Student").list();
                for (Iterator iter = student.iterator(); iter.hasNext();){
                    //集合中的元素是2个长度对象的数组(因为select查询了id,name两个属性)
                    Object[] obj = (Object[])iter.next();
                    //数据组中第一个元素是id,类型是int;第二个元素是name,类型是String(因为select中是id(int),name(String)顺序)
                    System.out.println(obj[0] + "," + obj[1]);
                }
                tx.commit();

    03 查询一个或多个属性,要求返回实体对象

    Query.list():返回结果集合元素是实体类对象

    * 查询一个或多个属性,要求返回实体对象,

    * 可采用HQL动态实例化实体对象

    * 实现条件:实体类中要一个构造方法,其参数是你需要查询的属性还需要一个无参构造方法(这是实体类的必需条件之一)

    * 然后在HQL语句中采用new 一个实体对象就可以了。

    * 如果查询所有学生的的id、姓名,要求list返回Student对象:select new Student(id,name) from Student

    * 这样session.createQuery().list()返回的就是Student实体对象

    session = HibernateUtils.getSession();
    
    tx = session.beginTransaction();           
    
    //如果认为返回数组不够对象化,可以采用hql动态实例化Student对象,此时list中为Student对象集合。
    
    //当然Student实体类中要有以id、name为参数的构造方法,和一个无参构造方法(是实体类必要条件之一)
    
    List students = session.createQuery("select new Student(id, name) from Student").list();
    for (Iterator iter = students.iterator(); iter.hasNext();){
    Student student = (Student)iter.next();
        System.out.println(student.getId() + "," + student.getName());
    }

    04 使用别名查询

    HQL语句中,可以使用别名查询,可以使用空格或as进行命名别名

    1、select s.id, s.name from Student s
    
    2、select s.id, s.name from Student as s

    2.实体对象查询

     2.1简单的实体对象查询

         * 语法:from 实体类(如果:session.createQuery("from Student");

         * 可以忽略select

         * Query.list():返回实体对象集合(Student对象集合)

        session = HibernateUtils.getSession();
    
                tx = session.beginTransaction();          
                //返回Student对象的集合
                //可以忽略select
    
                List students = session.createQuery("from Student").list();
    
                for (Iterator iter = students.iterator(); iter.hasNext();){
                    Student student = (Student)iter.next();
                    System.out.println(student.getName());
                }
                tx.commit();

    2.2 实体对象使用别名查询

    实体类对象查询,也可以使用别名,同样可以使用空格或as

    1、List students = session.createQuery("from Student s").list();
    
    2、List students = session.createQuery("from Student as s").list();

    2.3使用select查询实体对象

        如果使用select查询实体对象,必须采用别名,可以用空格或as关键字, select后直接跟别名就可以了。

    1、List students = session.createQuery("select s from Student s").list();
    
    2、List students = session.createQuery("select s from Student as s").list();

    2.4 HQL不支持select * from ……

    HQL不支持select * from ……查询,否则会抛异常,但*可以用是特定的函数中。

    2.5 query.iterate查询数据

    * query.iterate()方式返回迭代查询

         * 会开始发出一条语句:查询所有记录ID语句

         * Hibernate: select student0_.id as col_0_0_ from t_student student0_

         * 然后有多少条记录,会发出多少条查询语句。

         * n + 1问题:n:有n条记录,发出n条查询语句;1 :发出一条查询所有记录ID语句。

         * 出现n+1的原因:因为iterate(迭代查询)是使用缓存的,

                        第一次查询数据时发出查询语句加载数据并加入到缓存,以后再查询时hibernate会先到ession缓存(一级缓存)中查看数据是否存在,如果存在则直接取出使用,否则发出查询语句进行查询。

    session = HibernateUtils.getSession();
                tx = session.beginTransaction();         
                /**
                 * 出现N+1问题
                 * 发出查询id列表的sql语句
                 * Hibernate: select student0_.id as col_0_0_ from t_student student0_
                 *
                 * 再依次发出根据id查询Student对象的sql语句
                 * Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_,
                 * student0_.createTime as createTime1_0_, student0_.classesid as classesid1_0_
                 * from t_student student0_ where student0_.id=?
                 */
                Iterator students = session.createQuery("from Student").iterate();        
                while (students.hasNext()){
                    Student student = (Student)students.next();
                    System.out.println(student.getName());
                }
    
     
    
    tx.commit();

    2.6 query.list()和query.iterate()的区别

    先执行query.list(),再执行query.iterate,这样不会出现N+1问题,

         * 因为list操作已经将Student对象放到了一级缓存中,所以再次使用iterate操作的时候

         * 它首先发出一条查询id列表的sql,再根据id到缓存中取数据,只有在缓存中找不到相应的

         * 数据时,才会发出sql到数据库中查询

    List students = session.createQuery("from Student").list();
    
                for (Iterator iter = students.iterator(); iter.hasNext();){
                    Student student = (Student)iter.next();
                    System.out.println(student.getName());
                }                       System.out.println("---------------------------------------------------------");
    
                 // 不会出现N+1问题,因为list操作已经将数据加入到一级缓存。
                Iterator iters = session.createQuery("from Student").iterate();
                while (iters.hasNext()){
                    Student student = (Student)iters.next();
                    System.out.println(student.getName());
    
                }

    2.7 两次query.list()

         * 会再次发出查询sql

         * 在默认情况下list每次都会向数据库发出查询对象的sql,除非配置了查询缓存

         * 所以:虽然list操作已经将数据放到一级缓存,但list默认情况下不会利用缓存,而再次发出sql

         * 默认情况下,list会向缓存中放入数据,但不会使用数据。

    List students = session.createQuery("from Student").list();
            
                for (Iterator iter = students.iterator(); iter.hasNext();){
                    Student student = (Student)iter.next();
                    System.out.println(student.getName());
                }
                      System.out.println("------------------------------------------------");
              
                //会再次发现SQL语句进行查询,因为默认情况list只向缓存中放入数据,不会使用缓存中数据
                students = session.createQuery("from Student").list();
              
                for (Iterator iter = students.iterator(); iter.hasNext();){
                    Student student = (Student)iter.next();
                    System.out.println(student.getName());
    
                }

    3.条件查询

    where 语句后可以使用实体对象属性进行条件判断

         * 例如:查询姓名最后为1的所有学生的id、姓名

         *      select id, name from Student where name like '%1'

         * 注:条件查询时,where后面跟实体对象属性名进行条件过滤

         *    like:是HQL的模糊查找

         *    % :代表是一个或多个字符

         *  当然也可以使用别名方式进行。

         *  select id, name from Student as s where s.name like '%1'

    3.1条件查询 拼字符串

        拼字符串:就是把参数及参数值使用 + 等方式连成一个字符串成为HQL语句使用

    List students = session.createQuery("select id, name from Student where name like '%1'").list();
    
    for (Iterator iter = students.iterator(); iter.hasNext();){
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + "," + obj[1]);
    }

    3.2 条件查询 点位符方式

    hql语句中,使用问号("?"),来占用参数的位置,

    然后再用query.setParameter(index,value)对象设置参数值即可

             query.setParameter(index,value):

    index:点位符的位置,是从0开始; value:参数值,传递的参数值,不用单引号引起来

        Query query = session.createQuery("select id, name from Student where name like ?");
        query.setParameter(0, "%1");//返回Query
        List students = query.list();          
        for (Iterator iter = students.iterator(); iter.hasNext();){
            Object[] obj = (Object[])iter.next();
            System.out.println(obj[0] + "," + obj[1]);
        }

    3.3 Hibernate支持方法链

    在点位方式查询中的行1、2、3可以简化时一条,并且使用导航位。因为上面1~3行代码可以简化如下

                List students = session.createQuery("select id, name from Student where name like ?")
                                .setParameter(0, "%1")
                                .list();

    3.4 条件查询 参数名传递方式

         * 使用:冒号(:) + 参数名,设置参数名

         * 例如: select id, name from Student where name like :myname

         * 然后再使用query.setParameter(String s,Object value),根据参数名设置参数值

    List students = session.createQuery("select id, name from Student where name like :myname and  id = :myid")
                    .setParameter("myname", "%1")
                    .setParameter("myid", 12)
                    .list();           
    
    for (Iterator iter = students.iterator(); iter.hasNext();){
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + "," + obj[1]);
    }

    3.5条件查询 包含条件in

    in 关键字的使用方法同SQL中的使用方法一样。

    可以使用字符拼串方式进行

        select id, name from Student where id in(1, 2, 4)

    可以使用占位符方式进行

        select id, name from Student where id in(?, ?, ?)

        缺点:这种方式只能确定几个条件,本例中,只能使用3个参数

    可以使用参数名方式进行(推荐)

        select id, name from Student where id in(:myids)

    例一:点位符方式:

    List students = session.createQuery("select id, name from Student where id in(?, ?, ?)")
                        .setParameter(0, 1)
                        .setParameter(1, 3)
                        .setParameter(2, 4)
                        .list();
    
        for (Iterator iter = students.iterator(); iter.hasNext();){
            Object[] obj = (Object[])iter.next();
            System.out.println(obj[0] + "," + obj[1]);
    }

    例二:参数名方式

        当in使用参数名称方式传参数时,则需要使用setParameterList(参数名,对象数组/集合)来动态设置参数值的个数及值,这样事前不必需要确定的参数个数了,非常的方便

        List students = session.createQuery("select id, name from Student where id in(:myids)")
                        .setParameterList("myids", new Object[]{1,2,3,6,8})
                        .list();
    
        for (Iterator iter = students.iterator(); iter.hasNext();){
            Object[] obj = (Object[])iter.next();
            System.out.println(obj[0] + "," + obj[1]);
        }

    4.使用SQL中的函数

    查询20082月创建的学生

    List students = session.createQuery("select id, name from Student where date_format(createTime,'%Y-%m') = ?")
                    .setParameter(0, "2008-02")
                    .list();
    
    for (Iterator iter = students.iterator(); iter.hasNext();){
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + "," + obj[1]);
    }

    查询2008-01-102008-02-15创建的学生(采用between)

    //因为createTime的类型是date类型,因此参数也需要是Date类型
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                //查询2008-01-10到2008-02-15创建的学生
                List students = session.createQuery("select id, name from Student where createTime between ? and ?")
                                .setParameter(0, sdf.parse("2008-01-10 00:00:00"))
                                .setParameter(1, sdf.parse("2008-02-15 23:59:59"))
                                .list();
    
                for (Iterator iter = students.iterator(); iter.hasNext();){
                    Object[] obj = (Object[])iter.next();
                    System.out.println(obj[0] + "," + obj[1]);
                }

    5.支持原生SQL查询

    Hibernate可以支持原生SQL查询,也就是可以直接使用SQL语句进行查询

    List students = session.createSQLQuery("select * from t_student").list();

     

    for (Iterator iter = students.iterator(); iter.hasNext();) {

        Object[] obj = (Object[]) iter.next();

        System.out.println(obj[0] + "," + obj[1]);

    }

    只是所使用的session.createSQLQuery()方法,其返回同createQuery是一样的Query

    6.外置命名查询

    就是把hql放在一个配置文件中,让hql和程序偶合程度降低

        方法:在映射文件中采用<query>标签来定义hql,可以放在任务一个映射文件中

             在程序中采用session.getNameQuery(queryName)方法得到Query对象,就可以进行相应的处理了。

        <query name="searchStudents">
    
    <!—防止一些特殊的符号,让XML出错,可以使用 <![CDATA[ ]]>-->
    
            <![CDATA[
    
                select s from Student s where s.id < ?
    
            ]]>
    
        </query>
    session = HibernateUtils.getSession();
    
                tx = session.beginTransaction();
    //红色为在映射文件中配置的<query>标签name属性的名称
                List students = session.getNamedQuery("searchStudents") //返回对象类型为Query
                                .setParameter(0, 10)//可采用方法链设置属性
                                .list();
    
                for (Iterator iter = students.iterator(); iter.hasNext();) {
                    Student student = (Student)iter.next();
                    System.out.println(student.getName());
                }

    7.查询过滤器

             定义一个条件,当我执行hql时,只要session没有关闭,都会加上这个条件。

    1、定义过滤器参数

    <!--
            使用标签<filter-def>定义过滤器,name:属性指定过滤器名称
                然后使用<filter-param>标签定义条件需要的参数名及类型
                   name:属于定义参数名
                    type:属于指定参数的类型,hibernate类型,也可以是java的包装类型
            注:过滤器可以定义在任务的映射文件中
         -->
        <filter-def name="filtertest">
            <filter-param name="myid" type="integer"/>
        </filter-def>

    2、 定义过滤器在什么地方使用

        在查询什么实体对象时用,这里是在查询Student对象时用。因此需要定义Student映射文件中的<class>标签中

        <class name="com.wjt276.hibernate.Student" table="t_student">
            <id name="id" column="id">
                <generator class="native"/>
            </id>
            <property name="name" column="name"/>
            <property name="createTime"/>
            <many-to-one name="classes" column="classesid"/>
            <!--
                使用<filter>标签来说明过滤器在此使用
                name:属于指定需要使用过滤器的名称
                condition:属于指定过滤的条件(注有些符号需要使用转义符<:&lt;)
                            例:condition="id &lt; :myid"表示id<myid参数
                            其中 ":myid"是参数名形式传参数,而myid是在定义过滤器时定义的参数名
             -->
            <filter name="filtertest" condition="id &lt; :myid"/>
        </class>

    3、使用过滤器(启用)

    需要使用session来启用过滤器,只要启用的session没有关闭,那么执行任何hql都会加入这个过滤器

    //为此session启用过滤器
                //需要设置过滤器名称,及设置相应的参数,当然根据参数名设置
                session.enableFilter("filtertest").setParameter("myid", 10);
                List students = session.createQuery("from Student").list();
     
                for (Iterator iter = students.iterator(); iter.hasNext();) {
                    Student student = (Student)iter.next();
                    System.out.print(student.getId() + "-");
                    System.out.println(student.getName());
    
    }

        这样,当执行hql查询语句时,就会加上过滤条件。输出语句如下:

    select student0_.id as id1_, student0_.name as name1_, student0_.createTime as createTime1_, student0_.classesid as classesid1_ from t_student student0_ where student0_.id < ?

    使用环境:

        如:系统一登录的时候,每个人录入的只能看到自己的,不能看到别人,可以在查询数据时,定义一个过滤器过滤录入人员用户名就可以了。

    8.分页查询

    Hibernate的分页查询是非常的方便,移槙性也方便

             代码如下:

    session = HibernateUtils.getSession();
                tx = session.beginTransaction();
                List students = session.createQuery("from Student")
                                .setFirstResult(0)//从第几条记录开始查询
                                .setMaxResults(2)//每页显示多少条记录
                                .list();
    
                for (Iterator iter = students.iterator(); iter.hasNext();) {
                    Student student = (Student) iter.next();
                    System.out.println(student.getId() + "-" + student.getName());
                }
                tx.commit();

    输出相应的SQL语句:

    Hibernate: select student0_.id as id1_, student0_.name as name1_, student0_.createTime as createTime1_, student0_.classesid as classesid1_ from t_student student0_ limit ?

    //因为此处的开始记录是0,所以省略,非0则显示出来

    9.对象导航查询

             在hql中采用点(“.”)进行导航

             如何:查询班级名称中包含1的所有学生的记录(s.classes.name)

    session = HibernateUtils.getSession();
    
                tx = session.beginTransaction();
                List students = session.createQuery("select s.id, s.name from Student s where s.classes.name like '%1'").list();//采用点(.)进行导航查询
    
                for (Iterator iter = students.iterator(); iter.hasNext();) {
                    Object[] obj = (Object[]) iter.next();
                    System.out.println(obj[0] + "," + obj[1]);
                }
                tx.commit();

    Hibernate: select student0_.id as col_0_0_, student0_.name as col_1_0_ from t_student student0_, t_classes classes1_ where student0_.classesid=classes1_.id and (classes1_.name like '%1')

    10.连接查询

    • 内连
    • 外连接(左连接、右连接)

    1、内连接查询

    查询学生所在班的名称及学生姓名

                //内连接关键字inner可以省略
                List students = session.createQuery("select c.name, s.name from Student s inner join s.classes c").list();
           
                for (Iterator iter = students.iterator(); iter.hasNext();){
                    Object[] obj = (Object[])iter.next();
                    System.out.println(obj[0] + "," + obj[1]);
                }

    2、左连接查询

    查询所有班级的名称(包括没有学生的班级)及班级里学生的姓名

                List students = session.createQuery("select c.name, s.name from Classes c left join c.students s ").list();
    
                for (Iterator iter = students.iterator(); iter.hasNext();){
                    Object[] obj = (Object[])iter.next();
                    System.out.println(obj[0] + "," + obj[1]);
                }

    3、右连接查询

    查询所有学生的姓名(包括没有班级的学生)及所在班级的名称

                List students = session.createQuery("select c.name, s.name from Classes c right join c.students s ").list();
             
                for (Iterator iter = students.iterator(); iter.hasNext();){
                    Object[] obj = (Object[])iter.next();
                    System.out.println(obj[0] + "," + obj[1]);
                }

    11.统计查询

    Count   max min sun ……

    session = HibernateUtils.getSession();
    
                tx = session.beginTransaction();
    
    //          List students = session.createQuery("select count(*) from Student").list();
    //          Long count = (Long)students.get(0);//因为返回的list中只有一个元素,所以使用get(0)
    //          System.out.println(count);
              
                //Query.uniqueResult()如果返回值是唯一的一个值,那么返回真实值,否则返回null
                //此处只返回一个值count(*),所以可以接受到值
                Long count = (Long)session.createQuery("select count(*) from Student").uniqueResult();
                System.out.println(count);          
                tx.commit();

    12.分组查询

    * 取每个班级有多少学生

    * 输入班级名称及学生数

    session = HibernateUtils.getSession();
    
                tx = session.beginTransaction();
                List students = session.createQuery("select c.name, count(*) from Student s join s.classes c group by c.name order by c.name").list();
                for (Iterator ite = students.iterator(); ite.hasNext();){
                    Object[] obj = (Object[])ite.next();
                    System.out.println(obj[0] + ", " + obj[1]);
                }       
                tx.commit();

    12.dml风格查询

    session = HibernateUtils.getSession();
    
                tx = session.beginTransaction();
    
                session.createQuery("update Student s set s.name = ? where s.id < ?")
                        .setParameter(0, "李四")
                        .setParameter(1, 5)
                        .executeUpdate();      
                tx.commit();

    尽量少用,因为和缓存不同步

  • 相关阅读:
    八、UIViewController们之间的协作——Segue
    七、UIViewController导航栏
    六、APP开发的主角——UIViewController
    五、UI开发之核心基础——约束(深入)
    四、UI开发之核心基础——约束(实用)
    三、UI开发之核心基础——约束(入门)
    iOS开发笔记错误集
    Unity中内嵌网页插件UniWebView使用总结
    利用Aspose.Word控件实现Word文档的操作
    ReSharper 配置及用法(ZHUANG)
  • 原文地址:https://www.cnblogs.com/crazylqy/p/4080938.html
Copyright © 2011-2022 走看看