Hibernateの検索方式(HQL/QBC/ローカルSQL)


一、概説
  • Hibernateは、次のようなオブジェクトを検索する方法を提供します.
  • ナビゲーションオブジェクト図:ロードされたオブジェクトに基づいて他のオブジェクト
  • にナビゲートする.
  • OID:オブジェクトのOIDに従ってオブジェクト
  • を検索する.
  • HQL:オブジェクト向けHQLクエリ文
  • を使用
  • QBC:QBC(Query By Criteria)APIを使用してオブジェクト
  • を検索する
  • ローカルSQL:ローカル・データベースを使用したSQLクエリー文

  • 二、HQL
  • HQLは、次の機能を持つオブジェクト向けのクエリ文です.
  • クエリー文で各種クエリー条件
  • を設定する.
  • は、投影クエリーをサポートする、すなわち、オブジェクトの一部の属性
  • のみを取得する.
  • はページングクエリ
  • をサポートする.
  • 接続クエリー
  • をサポート
  • はパケットクエリ
  • をサポートする.
  • は、内蔵集積関数
  • を提供する.
  • サブクエリ
  • をサポート
  • 動的バインドパラメータ
  • をサポート
  • は、ユーザ定義のSQL関数または標準のSQL関数
  • を呼び出すことができる.
  • ステップ:
  • 1.SessionのcreateQuery()メソッドを使用して、HQLクエリ文を含むQueryオブジェクトを作成します.HQLクエリ文に名前付きパラメータを含めることができます
    2.動的バインドパラメータ
    3.Query関連メソッドを呼び出してクエリー文を実行する
  • Queryインタフェースはメソッドチェーンプログラミングスタイルをサポートし、そのsetXxx()メソッドは自身のインスタンス
  • を返す.
  • バインドパラメータ
  • Hibernateのパラメータバインドメカニズムは、JDBC APIにおけるPreparedStatementの事前定義SQL文機能
  • に依存する.
  • HQLのパラメータバインドには、次の2つの形式があります.
  • パラメータ名でバインド:名前付きパラメータは":"で始まる
  • パラメータ位置によるバインド:パラメータ位置
  • を「?」で定義します.
  • 関連メソッド:
  • setEntity():パラメータを永続化クラスにバインドする
  • setParameter():指定Hibernateマッピングタイプ
  • を示す任意のタイプのパラメータをバインドします.

  • HQL ORDER BYキーワードによるクエリ結果のソート
  • エンティティークラス(対応するプロファイルは省略)
    Department.java
    public class Department {
    ​
        private Integer id;
        private String name;
        
        private Set emps = new HashSet<>();
    }

    Employee.java
    public class Employee {
    ​
        private Integer id;
        private String name;
        private float salary;
        private String email;
      
        
        public Employee() {}
      
        public Employee(String email, float salary, Department dept) {
            this.salary = salary;
            this.email = email;
            this.dept = dept;
        }
    ​
      
      ///get(),set()  
    }

    テスト:
        private SessionFactory sessionFactory;
        private Session session;
        private Transaction transaction;
        
        @Before
        public void init(){
            Configuration configuration = new Configuration().configure();
            ServiceRegistry serviceRegistry = 
                    new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                                                .buildServiceRegistry();
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            
            session = sessionFactory.openSession();
            transaction = session.beginTransaction();
        }
        
        @After
        public void destroy(){
            transaction.commit();
            session.close();
            sessionFactory.close();
        }
    ​
        @Test
        public void testHQLNamedParameter(){
            
            //1.    Query   
            //      . 
            String hql = "FROM Employee e WHERE e.salary > :sal AND e.email LIKE :email";
            Query query = session.createQuery(hql);
            
            //2.     
            query.setFloat("sal", 7000)
                 .setString("email", "%A%");
            
            //3.     
            List emps = query.list();
            System.out.println(emps.size());  
        }
        
        @Test
        public void testHQL(){
            
            //1.    Query   
            //       . 
            String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? AND e.dept = ? "
                    + "ORDER BY e.salary";
            Query query = session.createQuery(hql);
            
            //2.     
            //Query      setXxx             .
            Department dept = new Department();
            dept.setId(80); 
            query.setFloat(0, 6000)
                 .setString(1, "%A%")
                 .setEntity(2, dept);
            
            //3.     
            List emps = query.list();
            System.out.println(emps.size());  
        }

    ページングクエリ
  • setFirstResult(int firstResult):インデックス(開始値0)を設定する
  • .
  • setMaxResults(int maxResults):一度に最大インデックス化するオブジェクトの数を設定する
  •     @Test
        public void testPageQuery(){
            String hql = "FROM Employee";
            Query query = session.createQuery(hql);
            //   
            int pageNo = 22;
            //      
            int pageSize = 5;
            
            List emps = 
                                    query.setFirstResult((pageNo - 1) * pageSize)
                                         .setMaxResults(pageSize)
                                         .list();
            System.out.println(emps);
        }

    マッピング・ファイルで名前付きクエリー・ステートメントを定義するには
  • Hibernateでは、マッピングファイルに文字列形式のクエリ文
  • を定義できます.
  • 要素HQLクエリ文を定義するために使用され、要素と並んで
  • クエリ文に対応するQueryオブジェクト
  • をプログラムでSessionのgetNamedQuery()メソッドで取得する
         :minSal AND e.salary < :maxSal]]>
        @Test
        public void testNamedQuery(){
            Query query = session.getNamedQuery("salaryEmps");
            
            List emps = query.setFloat("minSal", 5000)
                                       .setFloat("maxSal", 10000)
                                       .list();
            
            System.out.println(emps.size()); 
        }

    投影クエリー
  • クエリー結果はエンティティの一部の属性のみを含み、selectキーワードによって
  • を実現する.
  • list()メソッドが返すセットには、クエリー結果のレコード
  • を表す配列タイプの要素が含まれます.
  • は、投影クエリが返すレコード
  • をラッピングするために、永続化クラス内のオブジェクトのコンストラクタを定義することができる.
  • は、distinctキーワードによって、クエリ結果が重複要素
  • を返さないことを保証することができる.
        @Test
        public void testFieldQuery2(){
            String hql = "SELECT new Employee(e.email, e.salary, e.dept) "
                    + "FROM Employee e "
                    + "WHERE e.dept = :dept";
            Query query = session.createQuery(hql);
            
            Department dept = new Department();
            dept.setId(80);
            List result = query.setEntity("dept", dept)
                                         .list();
            
            for(Employee emp: result){
                System.out.println(emp.getId() + ", " + emp.getEmail() 
                        + ", " + emp.getSalary() + ", " + emp.getDept());
            }
        }
        
        @Test
        public void testFieldQuery(){
            String hql = "SELECT e.email, e.salary, e.dept FROM Employee e WHERE e.dept = :dept";
            Query query = session.createQuery(hql);
            
            Department dept = new Department();
            dept.setId(80);
            List result = query.setEntity("dept", dept)
                                         .list();
            
            for(Object [] objs: result){
                System.out.println(Arrays.asList(objs));
            }
        }

    レポート照会
  • レポート・クエリーデータのグループ化および統計
  • HQLクエリ文では、次の集計関数を呼び出すことができます.
  • count()
  • min()
  • max()
  • sum()
  • avg()

  •     @Test
        public void testGroupBy(){
            String hql = "SELECT min(e.salary), max(e.salary) "
                    + "FROM Employee e "
                    + "GROUP BY e.dept "
                    + "HAVING min(salary) > :minSal";
            
            Query query = session.createQuery(hql)
                                 .setFloat("minSal", 8000);
            
            List result = query.list();
            for(Object [] objs: result){
                System.out.println(Arrays.asList(objs));
            }
        }

    切実な左外接続
  • left join fetchキーワード
  • list()メソッドが返す集合にはエンティティオブジェクトの参照が格納され、各Departmentオブジェクトに関連付けられたEmployee集合が初期化され、すべての関連するEmployeeのエンティティオブジェクト
  • が格納される.
  • クエリの結果に重複する要素が含まれる場合があり、1つのHashSetで重複する要素
  • をフィルタできます.
        @Test
        public void testLeftJoinFetch(){
    //      String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN FETCH d.emps";
            String hql = "FROM Department d INNER JOIN FETCH d.emps";
            Query query = session.createQuery(hql);
            
            List depts = query.list();
            depts = new ArrayList<>(new LinkedHashSet(depts));
            System.out.println(depts.size()); 
            
            for(Department dept: depts){
                System.out.println(dept.getName() + "-" + dept.getEmps().size());
            }
        }

    左外部ジョイン:
  • left joinキーワード
  • list()メソッドが返す集合に格納されるのは、オブジェクト配列タイプ
  • である.
  • プロファイルに基づいてEmployeeセットの検索ポリシー
  • を決定する.
  • list()メソッドで返されるセットにDepartmentオブジェクトを含める場合は、HQLクエリ文でselectキー
  • を使用できます.
        @Test
        public void testLeftJoin(){
            String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN d.emps";
            Query query = session.createQuery(hql);
            
            List depts = query.list();
            System.out.println(depts.size());
            
            for(Department dept: depts){
                System.out.println(dept.getName() + ", " + dept.getEmps().size()); 
            }
            
    //      String hql = "FROM Department d LEFT JOIN d.emps";
    //      List result = query.list(); 
    //      result = new ArrayList<>(new LinkedHashSet<>(result));
    //      System.out.println(result); 
    //      
    //      for(Object [] objs: result){
    //          System.out.println(Arrays.asList(objs));
    //      }
        }

    ないぶせつぞく
        @Test
        public void testLeftJoinFetch2(){
            String hql = "SELECT e FROM Employee e INNER JOIN e.dept";
            Query query = session.createQuery(hql);
            
            List emps = query.list();
            System.out.println(emps.size()); 
            
            for(Employee emp: emps){
                System.out.println(emp.getName() + ", " + emp.getDept().getName());
            }
        }

    三、QBC
  • QBCクエリは、Hibernateが提供するQBC APIを使用してオブジェクト
  • をクエリする
        @Test
        public void testQBC4(){
            Criteria criteria = session.createCriteria(Employee.class);
            
            //1.     
            criteria.addOrder(Order.asc("salary"));
            criteria.addOrder(Order.desc("email"));
            
            //2.       
            int pageSize = 5;
            int pageNo = 3;
            criteria.setFirstResult((pageNo - 1) * pageSize)
                    .setMaxResults(pageSize)
                    .list();
        }
        
        @Test
        public void testQBC3(){
            Criteria criteria = session.createCriteria(Employee.class);
            
            //    :    Projection    :     Projections        
            criteria.setProjection(Projections.max("salary"));
            
            System.out.println(criteria.uniqueResult()); 
        }
        
        @Test
        public void testQBC2(){
            Criteria criteria = session.createCriteria(Employee.class);
            
            //1. AND:    Conjunction   
            //Conjunction        Criterion   
            //         Criterion   
            Conjunction conjunction = Restrictions.conjunction();
            conjunction.add(Restrictions.like("name", "a", MatchMode.ANYWHERE));
            Department dept = new Department();
            dept.setId(80);
            conjunction.add(Restrictions.eq("dept", dept));
           //name like "%a%" and dept=Department [id=80]
            System.out.println(conjunction); 
            
            //2. OR
            Disjunction disjunction = Restrictions.disjunction();
            disjunction.add(Restrictions.ge("salary", 6000F));
            disjunction.add(Restrictions.isNull("email"));
            //salary>=6000 or email is null
            System.out.println(disjunction);    
          
           //        and    
            criteria.add(disjunction);
            criteria.add(conjunction);
            
            criteria.list();
        }
        
        @Test
        public void testQBC(){
            //1.      Criteria   
            Criteria criteria = session.createCriteria(Employee.class);
            
            //2.       :   QBC         Criterion    
            //Criterion      Restrictions        
            criteria.add(Restrictions.eq("email", "SKUMAR"));
            criteria.add(Restrictions.gt("salary", 5000F));
            
            //3.     
            Employee employee = (Employee) criteria.uniqueResult();
            System.out.println(employee); 
        }

    四、ローカルSQL
        @Test
        public void testNativeSQL(){
            String sql = "INSERT INTO gg_department VALUES(?, ?)";
            Query query = session.createSQLQuery(sql);
            
            query.setInteger(0, 280)
                 .setString(1, "ATGUIGU")
                 .executeUpdate();
        }