• Hibernate学习笔记--------4.查询


    一、Get/Load

    Get方法是立即检索,而load是延迟检索,他们都是根据主键进行查询。在<class>标签中,若把lazy属性改为false,load方法就会立即检索,class中的lazy属性仅对load方法有效。在使用load时,当数据库没有找到数据时,会有ObjectNotFoundException,异常。

    1   public void LazyTest() {
    2         //lazy 改为false或者true,查看打印sql的时机
    3         Tb_User u = session.load(Tb_User.class, "1");
    4         //System.out.println(u.getName()); 
    5     }

    二、1-n或多对多的查询

    2.1 set 标签的lazy属性 可以设置为三种值:true,false,extra。

    1. 默认为懒加载策略,即lazy默认为true
    2. Lazy为false时,会采用立即加载
    3. Extra会尽可能的延迟集合初始化的时机,可以重打印的sql语句发现,使用了count
      select
            count(ID) 
        from
            TB_ORDER 
        where
            userid =?

    2.2   set标签的batch-size属性,确定批量初始化集合元素的个数

    2.3   set标签的fetch属性,默认值为select,确定初始化集合的方式

      1.select ,通过正常的方式来初始化set

      2.subselect,通过子查询的方式来初始化所有的set集合,lazty属性有效,batch-size属性失效,此时sql语句

    Hibernate: 
        select
            orders0_.userid as userid6_0_1_,
            orders0_.ID as ID1_0_1_,
            orders0_.ID as ID1_0_0_,
            orders0_.NAME as NAME2_0_0_,
            orders0_.MONEY as MONEY3_0_0_,
            orders0_.COUNT as COUNT4_0_0_,
            orders0_.CREATETIME as CREATETIME5_0_0_,
            orders0_.userid as userid6_0_0_ 
        from
            TB_ORDER orders0_ 
        where
            orders0_.userid in (
                select
                    tb_user0_.ID 
                from
                    TB_USER tb_user0_
            )

      2.4  join,lazy会失效,采用左外连接查询。若使用hql查询,会忽略fetch=join属性

    三、n-1的查询

    1. many-to-one 的 lazy属性有三个取值:proxy 延迟检索,no-proxy,false 立即检索

    2.many-to-one 的 fetch属性有两个取值:select,join,作用和上面的一样。

    3.batch-size属性是加到1方的class标签上的,这里不是加到many-to-one上的!

    四、采用hql查询

    1.使用步骤:

    -用过Session的createQuery方法创建一个Query对象,参数为HQL语句

    -动态的绑定参数(按参数名字绑定 :参数名,按参数位置绑定 ?)

     1     //基于参数位置绑定参数值
     2     @Test
     3     public void test1(){
     4         Query query = session.createQuery("FROM Tb_User WHERE name = ? AND id = ?");
     5         query.setParameter(0, "1");
     6         query.setParameter(1, "1");
     7         List<Tb_User> list = query.getResultList();
     8         System.out.println(list.size());
     9     }
    10     
    11     //基于参数名称绑定参数值
    12     @Test
    13     public void test2(){
    14         Query query = session.createQuery("FROM Tb_User WHERE name = :name AND id = :id");
    15         query.setParameter("name", "1");
    16         query.setParameter("id", "1");
    17         List<Tb_User> list = query.getResultList();
    18         System.out.println(list.size());
    19     }

    -调用query相关方法执行查询语句

    2.分页查询  两个相关方法 setFirsetResult | setMaxResult

     1     //分页测试
     2     @Test
     3     public void pageTest(){
     4         Query query = session.createQuery("SELECT id FROM Tb_User");
     5         int pageNo = 2;//当前页数
     6         int pageSize = 4;//每页大小
     7         
     8         List<String> list = query
     9                 .setFirstResult((pageNo - 1) * pageSize)
    10                 .setMaxResults(4).getResultList();
    11         for(String u : list){
    12             System.out.println(u);
    13         }
    14     }

    3.命名查询 getNamedQuery

    命名查询可以让我们在xml中定义hql语句,在映射文件中,class标签外添加;这里用CDATA是因为若hql中有大于>或小于<等符号时,可以避免冲突

    <query name = "findUserByName">
        <![CDATA[FROM Tb_User a WHERE a.name = :name]]>
    </query>

    然后通过name属性来执行该语句

      @Test
        public void nameQuery(){
            Query query = session.getNamedQuery("findUserByName");
            List<Tb_User> list = query.setParameter("name", "1").getResultList();
            System.out.println(list.size());
        }

    4.投影查询 查询表中某些字段

    这里选择了两个字段,因此每条数据查询出来是一个object数组,由于有多条数据,所以就用了List<Object[]>来保存结果,若只查询一个字段,则可用List<T>来保存结果

        @Test
        public void filedQuery(){
            String hql = "SELECT a.id ,a.name FROM Tb_User a";
            Query query = session.createQuery(hql);
            List<Object[]> result = query.getResultList();
            
            for(Object[] objs: result){
                System.out.println(Arrays.asList(objs));
                //System.out.println(objs[0]);
            }
        }

    当然,也可以在查询出来的同时初始化这个类,如下,注意需要在Tb_User中添加一个只有id和name的构造函数。

        @Test
        public void filedQuery2(){
            String hql = "SELECT new Tb_User( a.id ,a.name ) FROM Tb_User a";
            Query query = session.createQuery(hql);
            List<Tb_User> result = query.getResultList();
            
            for(Tb_User u: result){
                System.out.println(u);
            }
        }

    5.报表查询,hql可用GROUP BY 和 HAVING 关键字,可以调用一下的聚集函数

    -count()

    -min()

    -max()

    -sum()

    -avg()

    //查询每个用户的最大金额和最小金额
        @Test
        public void GroupQuery(){
            String hql = "SELECT min(a.money) ,max(a.money) FROM Tb_Order a "+
                         "GROUP BY a.user";
            Query query = session.createQuery(hql);
            List<Object[]> result = query.getResultList();
            
            for(Object[] objs: result){
                System.out.println(Arrays.asList(objs));
                //System.out.println(objs[0]);
            }
        }

    6.左外连接

    左外连接有两种关键字:LEFT JOIN 和 LEFT JOIN FETCH

    LEFT JOIN FETCH的方式是查出来,并且立即初始化集合,集合可能包含有重复的元素,需要去重。去重可用hql的distinct或者hashset集合

        @Test
        public void leftJoinFetch() {
            String hql = "From Tb_User a LEFT JOIN FETCH a.orders";
            
            //String hql = "SELECT DISTINCT a From Tb_User a LEFT JOIN FETCH a.orders"; //hql去掉重复的字段
            Query query = session.createQuery(hql);
            List<Tb_User> list = query.getResultList();
            //list = new ArrayList<Tb_User>(new LinkedHashSet<Tb_User>(list));//hashset去掉重复字段
            for(Tb_User u : list){
                System.out.println(u.getName() +"-"+ u.getOrders().size());
            }
        }

    LEFT JOIN方式,默认查出来每条数据是一个对象数组,每个对象数组包含了Tb_User和Tb_Order,但是他并没有初始话集合,初始化集合的操作需要更加映射文件的配置来。可能会有重复,但是只能用hql的distinct关键字去重 

        @Test
        public void leftJoin() {
            String hql = "From Tb_User a LEFT JOIN a.orders";
    
            Query query = session.createQuery(hql);
            List<Object[]> list = query.getResultList();
            
            for(Object[] objs : list){
                System.out.println(Arrays.asList(objs));
            }
        }

    这下面这种情况下,他会根据user映射文件的配置查询数据库得到他order的数量

        @Test
        public void leftJoin2() {
            String hql = "SELECT DISTINCT a From Tb_User a LEFT JOIN a.orders";
    
            Query query = session.createQuery(hql);
            List<Tb_User> list = query.getResultList();
            
            for(Tb_User u : list){
                System.out.println(u.getName() +"-"+ u.getOrders().size());
            }
        }

    内链接也有两个INNER JOIN FETCH 和INNER JOIN 和左外连接的区别在于他不会查询左表不符合条件的记录,在这里即是不返回订单为0的用户。

    五、QBC(Query By Criteria) 面向对象的查询

    使用Criteria的接口来实现

        @Test
        public void qbcTest(){
            //1.创建一个Criteria对象
            Criteria criteria = session.createCriteria(Tb_User.class);
            //2.添加查询条件
            criteria.add(Restrictions.eq("id","1"));
            //3.执行查询
            Tb_User u = (Tb_User)criteria.uniqueResult();
            System.out.println(u);
        }

    他们的and或者or的查询方式

        @Test
        public void qbcTest2(){
            Criteria criteria = session.createCriteria(Tb_User.class);
            // AND : 使用Conjunction表示
            Conjunction conjunction = Restrictions.conjunction();
            conjunction.add(Restrictions.like("name","1",MatchMode.ANYWHERE));
            conjunction.add(Restrictions.eq("id", "1"));
            criteria.add(conjunction);
            System.out.println(criteria.list());
            //or
            Criteria criteria1 = session.createCriteria(Tb_Order.class);
            Disjunction disjunction = Restrictions.disjunction();
            disjunction.add(Restrictions.ge("money",2.0));
            disjunction.add(Restrictions.eq("name", "aa"));
            criteria1.add(disjunction);
            System.out.println(criteria1.list().size());
        }

    criteria的统计查询

        @Test
        public void qbcTest3(){
            
            Criteria criteria = session.createCriteria(Tb_Order.class);
            //统计查询:使用prijection来表示
            criteria.setProjection(Projections.max("money"));
            //添加排序
            //criteria.addOrder(Order.asc("id"));
            System.out.println(criteria.uniqueResult());
        }

    他的分页和query.getResultList方法是一样的

    六、本地sql查询

    若自己写sql查询出来是一个对象数组,使用起来感觉怪怪的。

        @Test
        public void nativeSql(){
            String sql = "select * from Tb_User where name = :name";
            Query query = session.createSQLQuery(sql);
            query.setParameter("name", "1");
            List<Object[]> list = query.getResultList();
            for(Object[] u : list){
                System.out.println(Arrays.asList(u));
            }
        }

    若要执行其他sql

        @Test
        public void nativeSql(){
            UUID u = UUID.randomUUID();
            String sql = "insert into Tb_User(id,name) values (:id,:name)";
            Query query = session.createSQLQuery(sql);
            query.setParameter("id", u.toString());
            query.setParameter("name", u.toString());
            query.executeUpdate();
        }

    Demo地址:http://pan.baidu.com/s/1kUT9H91

  • 相关阅读:
    题解 P2280 【[HNOI2003]激光炸弹】
    线段树求逆序对
    题解 P3378 【【模板】堆】
    动态规划-最大算式 蓝桥杯ALGO-116
    动态规划-树形动态规划-结点选择
    Trie树(字典树)-题解 P2580 【于是他错误的点名开始了】
    清北学堂-DAY2-数论专题-中国剩余定理(CRT)
    听课笔记--DP--Authentication Failed
    听课笔记--DP--最大子矩阵和
    多媒体基础
  • 原文地址:https://www.cnblogs.com/lzq1065763582/p/5723250.html
Copyright © 2020-2023  润新知