(十二)Hibernate的查询方式

一、OID检索方式

 

 按照对象的OID来查询对象。Session的get/load方法提供了这种功能。 

 如果应用程序中事先知道了OID,就可以使用这种查询对象的方式。 

 

  

二、导航对象图检索方式

 

根据已经加载的对象,导航到其他对象.

例如,对于已经加载的Customer对象,可以导航到所有关联的Order对象 

 

  

三、HQL检索方式

 

简介:

 

使用面向对象的HQL查询语言。Hibernate提供了Query接口,它是专门的HQL查询接口,能执行各种复杂的HQL语句。

 

HQL是面向对象的查询语言,和SQL查询语言有些类似,Hibernate提供的各种检索方式中,HQL是使用最广的一种检索方式。HQL封装了JDBC的细节

HQL和SQL本质是不一样的: 

    -HQL查询语言面向对象,Hibernate负责解析HQL语句,然后根据映射文件,把HQL语句翻译成SQL语句。HQL查询语句中主体是类和类的属性。 

    -SQL查询语言是和关系数据库绑定在一起的,SQL查询语句中主体是数据库表和表的字段。 

  

HQL查询的步骤 
-通过session的createQuery(HQL语句)方法创建一个Query对象 
-调用Query的list()方法执行查询语句。该方法返回List集合

 

(1)================= 查找所有对象 ====================

    public class Demo {

                    private Session session;

                    @Test
                    public void test() {
                        //读取配置文件
                        Configuration conf=new Configuration().configure();

                        //根据配置创建factory
                        SessionFactory sessionfactory=conf.buildSessionFactory();
                        session = sessionfactory.openSession(); 
                         Transaction ts=session.beginTransaction(); 
                         //HQL语句是面向对象的,from 类名 
                        List<Customer> customerlist=session.createQuery("from Customer").list();
                        System.out.println(customerlist);
                        ts.commit();
                        session.close();
                        sessionfactory.close();
                    }

                } 

  (2)================= HQL语句使用别名 ====================

例如:List< Customer > customerlist=session.createQuery(“from Customer as c”).list();

as关键字用来设置别名,as也可以省略。 from Customer c即可。

  (3)================= HQL语句选择查询 ====================

        选择查询是指仅查找某些属性。
        这时list()返回的集合中包括的是一个一个数组,每个数组中是一条记录。 

        List <Object[]> customerlist=session.createQuery("select id,name from Customer").list(); 
        for(Object[] obj:customerlist){
            System.out.println(Arrays.toString(obj));
        }

  (4)================= HQL语句投影查询 ====================

        基于选择查询的基础上,把查询到的属性封装到对象中,该对象的其他属性为null。
        该对象必须有对应的构造方法。

        List <Customer> customerlist=session.createQuery("select new Customer(id,name) from Customer").list();
        for(Customer c:customerlist){
            System.out.println(c.toString());
        }

        Customer类中必须有如下构造方法     
        public Customer(Integer id, String name) {
            this.id = id;
            this.name = name;
        }

  (5)================= HQL对查询结果排序 ====================

    HQL语言使用order by关键字对结果进行排序。
    asc为升序,desc为降序。 

    List <Customer> customerlist=session.createQuery("select new Customer(id,name) from Customer order by id desc").list();

  (6)================= HQL分页查询 ====================

        -setFirstResult(int index):设定从第几个对象开始检索,起始值为0。
        -setMaxResult(int count):设定一次检索的对象数目。默认情况下检索所有的对象。

            Query query=session.createQuery("select id,name from Customer");
            //从第一个对象开始
            query.setFirstResult(0);
            //查找两个对象
            query.setMaxResults(2);
            List result=query.list();

  (7)================= HQL语句中绑定参数 ====================

对于实际应用中,经常需要用户输入一些查询条件,我们返回符合查询条件的数据。
我们可以使用from Customer where name='"+name+"';来实现
但是这种方式是非常不安全的,会受到SQL注入等非法攻击。 

  

        Hibernate中使用参数绑定来避免以上问题。有两种方式 

        (1)使用?占位符绑定
                        占位符的索引从0开始。
                        Query query=session.createQuery("from Customer where id=?");
                        query.setInteger(0, 7);

                        Customer c=(Customer) query.uniqueResult();
                        System.out.println(c.toString());

                        Query提供了各种绑定数据类型的参数的方法setXxx(),如果参数为字符串类型,就调用setString(),如果参数为整数类型,就调用setInteger()等等。
                        这些setXxx()方法第一个参数代表占位符的索引,第二个代表参数值。

        (2) 使用参数名字绑定
                        在HQL中使用命名参数,命名参数以":"开头。
                        Query query=session.createQuery("from Customer where id=:a");
                        query.setInteger("a", 7);

                        Customer c=(Customer) query.uniqueResult();
                        System.out.println(c.toString()); 

                        这些setXxx()方法第一个参数是命名参数的名字,第二个参数是值。

  (8)================= HQL查询单个对象 ====================

        -uniqueResult()方法:返回单个对象  

                Query query=session.createQuery("from Customer where id=1");
                Customer c=(Customer) query.uniqueResult();
                System.out.println(c.toString());

  (9)================= HQL聚合函数和分组查询 ====================

        (1)HQL调用聚合函数
                -查询customer表所有记录数目
                            Query query=session.createQuery("select count(*) from Customer"); 
                            //该语句返回long类型
                            Long c=(Long) query.uniqueResult();
                            System.out.println(c.intValue());

                -查询最大ID
                            Query query=session.createQuery("select Max(id) from Customer");
                            Integer c=(Integer) query.uniqueResult();
                            System.out.println(c.intValue());


        (2)分组查询
                group by子句用来分组查询。

                -根据id分组,统计相同id的数目
                            Query query=session.createQuery("select id,count(*) from Customer group by id");
                            List<Object[]> list=query.list();
                            for(Object[] obj:list){
                                System.out.println(Arrays.toString(obj));
                            }

                -having子句用于为分组查询加上条件
                            Query query=session.createQuery("select id,count(*) from Customer group by id having id>8");
                            List<Object[]> list=query.list();
                            for(Object[] obj:list){
                                System.out.println(Arrays.toString(obj));
                            }

  (10)================= HQL连接查询 ====================

        -交叉连接:返回被连接的两个表所有数据行的笛卡儿积
        如果A表有5行记录,B表有7行记录,返回的结果就有35行记录
        显然,会产生很多没有意义的数据。

                Query query=session.createQuery("from Customer,Order");
                List<Object[]> list=query.list();
                for(Object[] obj:list){
                    System.out.println(Arrays.toString(obj));
                }

        -隐式内连接
            在交叉连接基础上,通过条件来过滤一些无意义的数据,达到内连接的效果。
                Query query=session.createQuery("from Customer c,Order o where o.customer=c");
                List<Object[]> list=query.list();
                for(Object[] obj:list){
                    System.out.println(Arrays.toString(obj));
                }

        -显式内连接
            使用inner join关键字表示内连接。inner可以省略,只使用join。
            调用list()方法返回的集合中存放的是每个元素对应的记录,每个元素都是数组类型。

                Query query=session.createQuery("from Customer c inner join c.orders"); 
                List<Object[]> list=query.list();
                for(Object[] obj:list){
                    System.out.println(Arrays.toString(obj));
                }


        -迫切内连接
            使用inner join fetch关键字表示迫切内连接。
            调用list()方法返回的集合中存放的是Customer对象的引用,每个Customer对象的Orders集合都被初始化,存放所有关联的Order对象。

                Query query=session.createQuery("from Customer c inner join  c.orders");
                List <Object> list=query.list();
                for(Object obj:list){
                    System.out.println(obj);
                } 

        -左外连接
            在连接查询中,连接左端的表中的所有的行全部显示,并且能在右端的表中找到匹配的行,如果右端表中没能找到左端匹配的行,则对应NULL.
            使用left join关键字表示左外连接。
            返回的list集合中存放的是多个对象数组。   
            Query query=session.createQuery("from Customer c left join  c.orders");
            List<Object[]> list=query.list();
            for(Object[] obj:list){
                System.out.println(Arrays.toString(obj));
            }

        -迫切左外连接
            使用left join fetch关键字表示迫切左外连接。
            list()方法返回的集合中存放的是Customer对象的引用,每个Customer的Orders集合都被初始化,存放关联的Order对象。
                Query query=session.createQuery("from Customer c left join fetch c.orders");
                List<Object> list=query.list();
                for(Object obj:list){
                    System.out.println(obj);
                }

        -右外连接
            和左外连接一样,连接右端表中的行全部显示,连接左端找到匹配的行,如果未能找到匹配的行,则用NULL代替
            使用right join关键字表示右外连接。
            Query query=session.createQuery("from Customer c right join  c.orders");
            List<Object[]> list=query.list();
            for(Object[] obj:list){
                System.out.println(Arrays.toString(obj));
            }

        -迫切右外连接
            Query query=session.createQuery("from Customer c right join fetch  c.orders");
            List<Object> list=query.list();
            for(Object obj:list){
                System.out.println(obj);
            }

  (11)================= 在映射文件中定义命名查询语句 ====================

前面的例子中,HQL查询语句都写在程序代码中。Hibernate允许在映射文件中定义字符串形式的查询语句。

            <class name="com.cad.domain.Customer" table="customer" >
                <id name="id" column="id">
                    <generator class="native"></generator>
                </id>
                <property name="name" column="name"></property>
                <set name="orders" batch-size="3" fetch="subselect">
                    <key column="cid"/>
                    <one-to-many class="com.cad.domain.Order" />    
                </set>
                <!--定义局部命名查询语句-->
                <query name="bcd"><![CDATA[from Order]]></query>
            </class>
            <!--定义全局命名查询语句-->
            <query name="abc"><![CDATA[from Customer]]></query>

            //调用全局的命名查询语句
            Query query=session.getNamedQuery("abc");
            //调用局部的命名查询语句
            Query query=session.getNamedQuery("com.cad.domain.Customer.bcd");
            List<Object> list=query.list();
            for(Object obj:list){
                System.out.println(obj);
            }

 

 

四、QBC检索方式

 

使用QBC(Query By Criteria)API检索对象。封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。 

QBC检索方式的步骤
        -调用Session的createCriteria()方法创建一个Criteria对象
        -设定查询条件
        -调用Criteria接口的list()方法执行查询语句。返回List集合。 

 

  (1)================= 查询所有对象 ====================

            //传递类名.class即可
            Criteria criteria=session.createCriteria(Customer.class);
            List<Customer> l=criteria.list();
             for(Customer c:l){
                 System.out.println(c);
             }

  (2)================= QBC对查询结果进行排序 ====================

        QBC使用org.hibernate.criterion.order类对查询结果排序。
        asc为升序,desc为降序。 

         Criteria criteria=session.createCriteria(Customer.class);
         criteria.addOrder(org.hibernate.criterion.Order.desc("id"));
         List<Customer> l=criteria.list();
         for(Customer c:l){
             System.out.println(c);
         }

  (3)================= QBC分页查询 ====================

    QBC的分页查询和HQL类似。Criteria接口也提供了方法。
            -setFirstResult(int index):设定从第几个对象开始检索,起始值为0。
            -setMaxResult(int count):设定一次检索的对象数目。默认情况下检索所有的对象。

                 Criteria criteria=session.createCriteria(Customer.class);
                 criteria.setFirstResult(0);
                 criteria.setMaxResults(2);
                 List<Customer> l=criteria.list();
                 for(Customer c:l){
                     System.out.println(c);
                 }

  (4)================= QBC设定查询条件 ====================

    必须创建一个Criterion对象来设定查询条件。Restrictions类提供了创建Criterion的方法。
            -Restrictions.eq()  等于
            -Restrictions.ne() 不等于
            -Restrictions.gt()  大于
              ..........等等很多方法 

        Criteria criteria=session.createCriteria(Customer.class);
        //查询id为7的Customer
         Criterion c1=Restrictions.eq("id", 7);
         criteria.add(c1);
         Customer c=(Customer) criteria.uniqueResult();
         System.out.println(c);

  (5)================= QBC检索单个对象 ====================

uniqueResult():返回单个对象

  

 

五、本地SQL检索方式

 

    可以使用原生的SQL语句来进行查询。
    本地SQL检索也是使用Query接口,通过Session的createSQLQuery(SQL语句)方法来创建Query。

        例子:
            Query query =session.createSQLQuery("select * from customer");
             List<Object[]> list=query.list();
             for(Object[] o:list){


                 System.out.println(Arrays.toString(o));
             } 

            默认情况下,SQLQuery返回的list集合中存放的是关系数据。每个元素都是Object[]数组。

        -addEntity()方法能把查询结果中每一行的数据封装成对象

                Query query =session.createSQLQuery("select * from customer").addEntity(Customer.class);
                 List<Customer> list=query.list(); 
                 for(Customer o:list){
                     System.out.println(o.toString());
                 }

 

  

 

 

  

 

posted @ 2018-08-09 23:55  跃小云  阅读(203)  评论(0编辑  收藏  举报