Hibernate讀書筆記-----SQL查詢 addScalar()或addEntity()

Hibernate除了支持HQL查詢外,還支持原生SQL查詢。   對原生SQL查詢執行的控制是通過SQLQuery接口進行的,通過執行Session.createSQLQuery()獲取這個接口。該接口是Query接口的子接口。

         執行SQL查詢步驟如下:

         1、獲取Hibernate Session對象

         2、編寫SQL語句

         3、通過Session的createSQLQuery方法創建查詢對象

         4、調用SQLQuery對象的addScalar()或addEntity()方法將選出的結果與標量值或實體進行關聯,分別用於進行標量查詢或實體查詢

         5、如果SQL語句包含參數,調用Query的setXxxx方法爲參數賦值

         6、調用Query的list方法返回查詢的結果集

        一、標量查詢

         最基本的SQL查詢就是獲得一個標量的列表:

[sql] view plaincopyprint?
session.createSQLQuery("select * from person_inf").list();  
session.createSQLQuery("select id,name,age from person_inf").list();

 它們都將返回一個Object組組成的List,數組每個元素都是person_inf表的一個字段值。Hibernate會使用ResultSetMetadata來判定返回的標量值的實際順序和類型。

         但是在JDBC中過多的使用ResultSetMetadata會降低程序的性能。所以爲了過多的避免使用ResultSetMetadata或者爲了指定更加明確的返回值類型,我們可以使用addScalar()方法:

[java] view plaincopyprint?
session.createSQLQuery("select * from person_inf")  
.addScalar("name",StandardBasicTypes.STRING)  
.addScalar("age",StandardBasicTypes.INT)[object Object]

         這個查詢指定了:

         1SQL查詢字符串。

         2要返回的字段和類型。

         它仍然會返回Object數組,但是此時不再使用ResultSetMetdata,而是明確的將name和age按照Stringint類型從resultset中取出。同時,也指明瞭就算query是使用*來查詢的,可能獲得超過列出的這三個字段,也僅僅會返回這三個字段。

         如果僅僅只需要選出某個字段的值,而不需要明確指定該字段的數據類型,則可以使用addScalar(String columnAlias)

實例如下:

[java] view plaincopyprint?
public void scalarQuery(){  
        Session session = HibernateUtil.getSession();  
        Transaction tx = session.beginTransaction();  
        String sql = "select * from person_inf";  
        List list = session.createSQLQuery(sql).  
                    addScalar("person_id",StandardBasicTypes.INTEGER).  
                    addScalar("name", StandardBasicTypes.STRING).  
                    addScalar("age",StandardBasicTypes.INTEGER).list();  
        for(Iterator iterator = list.iterator();iterator.hasNext();){  
            //每個集合元素都是一個數組,數組元素師person_id,person_name,person_age三列值 
            Object[] objects = (Object[]) iterator.next();  
            System.out.println("id="0; )
            System.out.println("name="+objects[1]);  
            System.out.println("age="+objects[2]);  
            System.out.println("----------------------------");  
        }  
        tx.commit();  
        session.close();  
    }

         從上面可以看出。標量查詢中addScalar()方法有兩個作用:

         1、指定查詢結果包含哪些數據列---沒有被addScalar選出的列將不會包含在查詢結果中。

         2、指定查詢結果中數據列的數據類型

        二、實體查詢

         上面的標量查詢返回的標量結果集,也就是從resultset中返回的數據。如果我們想要的結果是某個對象的實體,這是就可以通過addEntity()方法來實現。addEntity()方法可以講結果轉換爲實體。但是在轉換的過程中要注意幾個問題:

         1、查詢返回的是某個數據表的全部數據列

         2、該數據表有對應的持久化類映射

         這時纔可以通過addEntity()方法將查詢結果轉換成實體。

[java] view plaincopyprint?
session.createSQLQuery("select * from perons_inf").addEntity(Person.class).list;  
session.createSQLQuery("select id,name,age from person_inf").addEntity(Person.class).list();

         這個查詢指定:

         1SQL查詢字符串

         2要返回的實體

         假設Person被映射爲擁有id,name和age三個字段的類,以上的兩個查詢都返回一個List,每個元素都是一個Person實體。

         假若實體在映射時有一個many-to-one的關聯指向另外一個實體,在查詢時必須也返回那個實體(獲取映射的外鍵列),否則會導致發生一個"column not found"的數據庫錯誤。這些附加的字段可以使用*標註來自動返回,但我們希望還是明確指明,看下面這個具有指向teacher的many-to-one的例子:   

[java] view plaincopyprint?
sess.createSQLQuery("select id, name, age, teacherID from person_inf").addEntity(Person.class).list();

         這樣就可以通過person.getTeacher()獲得teacher了。

          實例:

[html] view plaincopyprint?

public void entityQuery(){  
    Session session = HibernateUtil.getSession();  
    Transaction tx = session.beginTransaction();  
    String sql = "select * from person_inf";  
    List list = session.createSQLQuery(sql).  
                addEntity(Person.class).    //指定將查詢的記錄行轉換成Person實體  
                list();       
    for (Iterator iterator = list.iterator();iterator.hasNext();) {  
        Person person = (Person) iterator.next();      //集合的每個元素都是一個Person對象  
        System.out.println("name="+person.getName());  
        System.out.println("age="+person.getAge());  
  
    }  
    tx.commit();  
    session.close();  
}  
上面的都是單表查詢,如果我們在SQL語句中使用了多表連接,則SQL語句可以選出多個數據表的數據。Hibernate支持將查詢結果轉換成多個實體。如果要將查詢結果轉換成多個實體,則SQL字符串中應該爲不同數據表指定不同別名,並且調用addEntity()方法將不同數據錶轉換成不同實體。如下
[java] view plaincopyprint?
public void multiEntityQuery(){  
    Session session = HibernateUtil.getSession();  
    Transaction tx = session.beginTransaction();  
    String sql = "select p.*,e.* from person_inf as p inner join event_inf as e" +  
                 " on p.person_id=e.person_id";  
    List list = session.createSQLQuery(sql)  
                .addEntity("p",Person.class)  
                .addEntity("e", MyEvent.class)  
                .list();  
    for(Iterator iterator = list.iterator();iterator.hasNext();){  
        //每個集合元素都是Person、MyEvent所組成的數組  
        Object[] objects = (Object[]) iterator.next();  
        Person person = (Person) objects[0];  
        MyEvent event = (MyEvent) objects[1];  
        System.out.println("person_id="+person.getId()+" person_name="+person.getName()+" title="+event.getTitle());  
          
    }  
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章