Hibernate原生SQL查詢使用addScalar()或addEntity()
阿新 • • 發佈:2019-02-05
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查詢就是獲得一個標量的列表:
它們都將返回一個Object陣列組成的List,陣列每個元素都是person_inf表的一個欄位值。Hibernate會使用ResultSetMetadata來判定返回的標量值的實際順序和型別。
但是在JDBC中過多的使用ResultSetMetadata會降低程式的效能。所以為了過多的避免使用ResultSetMetadata或者為了指定更加明確的返回值型別,我們可以使用addScalar()方法:
這個查詢指定了:
1、SQL查詢字串。
2、要返回的欄位和型別。
它仍然會返回Object陣列,但是此時不再使用ResultSetMetdata,而是明確的將name和age按照String和int型別從resultset中取出。同時,也指明瞭就算query是使用*來查詢的,可能獲得超過列出的這三個欄位,也僅僅會返回這三個欄位。
如果僅僅只需要選出某個欄位的值,而不需要明確指定該欄位的資料型別,則可以使用addScalar(String columnAlias)。
例項如下:
從上面可以看出。標量查詢中addScalar()方法有兩個作用:
1、指定查詢結果包含哪些資料列---沒有被addScalar選出的列將不會包含在查詢結果中。
2、指定查詢結果中資料列的資料型別
二、實體查詢
上面的標量查詢返回的標量結果集,也就是從resultset中返回的“裸”資料。如果我們想要的結果是某個物件的實體,這是就可以通過addEntity()方法來實現。addEntity()方法可以講結果轉換為實體。但是在轉換的過程中要注意幾個問題:
1、查詢返回的是某個資料表的全部資料列
2、該資料表有對應的持久化類對映
這時才可以通過addEntity()方法將查詢結果轉換成實體。
這個查詢指定:
1、SQL查詢字串
2、要返回的實體
假設Person被對映為擁有id,name和age三個欄位的類,以上的兩個查詢都返回一個List,每個元素都是一個Person實體。
假若實體在對映時有一個many-to-one的關聯指向另外一個實體,在查詢時必須也返回那個實體(獲取對映的外來鍵列),否則會導致發生一個"column not found"的資料庫錯誤。這些附加的欄位可以使用*標註來自動返回,但我們希望還是明確指明,看下面這個具有指向teacher的many-to-one的例子:
這樣就可以通過person.getTeacher()獲得teacher了。
例項:
上面的都是單表查詢,如果我們在SQL語句中使用了多表連線,則SQL語句可以選出多個數據表的資料。Hibernate支援將查詢結果轉換成多個實體。如果要將查詢結果轉換成多個實體,則SQL字串中應該為不同資料表指定不同別名,並且呼叫addEntity()方法將不同資料錶轉換成不同實體。如下
三、處理關聯和繼承
通過提前抓取將Event連接獲得,而避免初始化proxy帶來的額外開銷也是可能的。這是通過addJoin()方法進行的,通過這個方法可以講實體的關聯實體轉換成查詢物件。如下:
四、命名查詢
我們可以將SQL語句不放在程式中,而是放在配置檔案中。這樣可以更好地提高程式解耦。
Hibernate使用<sql-query.../>元素來配置命名SQL查詢,配置<sql-query.../>元素有一個必填的name屬性,該屬性用於指定該命名SQL查詢的名稱。
使用<sql-query.../>元素定義命名查詢時,可以包含如下幾個元素:
<return.../>:將查詢結果轉換成持久化實體
<return-join.../>:預載入持久化實體的關聯實體
<return-scalar.../>:將查詢的資料列轉換成標量值
在使用命名SQL查詢時,不需要呼叫addEntity()、addScalar()等方法。因為在配置命名SQL查詢時,已經指定了查詢返回的結果資訊。
[html] view plaincopyprint?
<!-- 命名SQL查詢 -->
五、呼叫儲存過程
Hibernate可以通過命名SQL查詢來呼叫儲存過程或者函式。對於函式,該函式必須返回一個結果集;對於儲存過程,該儲存過程的第一個引數必須傳出引數,且資料型別是結果集。
下面是一個簡單的儲存過程:
如果需要使用該儲存過程,可以先將其定義成命名SQL查詢,然後在程式中使用。
當使用原生SQL來呼叫儲存過程,應該為<sql-query.../>元素指定callable="true"。
程式與上面相同。
呼叫儲存過程需要注意以下幾個問題:
為了在Hibernate中使用儲存過程,你必須遵循一些規則.不遵循這些規則的儲存過程將不可用.如果你仍然想要使用他們, 你必須通過session.connection()來執行他們.這些規則針對於不同的資料庫.因為資料庫 提供商有各種不同的儲存過程語法和語義.
對儲存過程進行的查詢無法使用setFirstResult()/setMaxResults()進行分頁。
建議採用的呼叫方式是標準SQL92: { ? = call functionName(<parameters>) } 或者 { ? = call procedureName(<parameters>}.原生呼叫語法不被支援。
對於Oracle有如下規則:
函式必須返回一個結果集。儲存過程的第一個引數必須是OUT,它返回一個結果集。這是通過Oracle 9或10的SYS_REFCURSOR型別來完成的。在Oracle中你需要定義一個REF CURSOR型別,參見Oracle的手冊。
對於Sybase或者MS SQL server有如下規則:
儲存過程必須返回一個結果集。.注意這些servers可能返回多個結果集以及更新的數目.Hibernate將取出第一條結果集作為它的返回值, 其他將被丟棄。
對原生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查詢就是獲得一個標量的列表:
<span style="font-family:SimSun;"><span style="font-size:12px;">session.createSQLQuery("<span class="operator"><span style="background-color: rgb(246, 246, 246);"><span class="keyword" style="font-weight: bold;">select</span> * <span class="keyword" style="font-weight: bold;">from</span> person_inf<span class="string" style="color:#dd1144;">").list(); session.createSQLQuery("</span><span class="keyword" style="font-weight: bold;">select</span> id,name,age <span class="keyword" style="font-weight: bold;">from</span> person_inf<span class="string" style="color:#dd1144;">").list();</span></span></span></span></span>
它們都將返回一個Object陣列組成的List,陣列每個元素都是person_inf表的一個欄位值。Hibernate會使用ResultSetMetadata來判定返回的標量值的實際順序和型別。
但是在JDBC中過多的使用ResultSetMetadata會降低程式的效能。所以為了過多的避免使用ResultSetMetadata或者為了指定更加明確的返回值型別,我們可以使用addScalar()方法:
<span style="font-family:SimSun;"><span style="font-size:12px;">session.createSQLQuery("<span class="operator"><span style="background-color: rgb(246, 246, 246);"><span class="keyword" style="font-weight: bold;">select</span> * <span class="keyword" style="font-weight: bold;">from</span> person_inf<span class="string" style="color:#dd1144;">") .addScalar("</span>name<span class="string" style="color:#dd1144;">",StandardBasicTypes.STRING) .addScalar("</span>age<span class="string" style="color:#dd1144;">",StandardBasicTypes.INT) .list();</span></span></span></span></span>
這個查詢指定了:
1、SQL查詢字串。
2、要返回的欄位和型別。
它仍然會返回Object陣列,但是此時不再使用ResultSetMetdata,而是明確的將name和age按照String和int型別從resultset中取出。同時,也指明瞭就算query是使用*來查詢的,可能獲得超過列出的這三個欄位,也僅僅會返回這三個欄位。
如果僅僅只需要選出某個欄位的值,而不需要明確指定該欄位的資料型別,則可以使用addScalar(String columnAlias)。
例項如下:
<font face="SimSun"><span style="font-size:12px;"><span style="background-color: rgb(246, 246, 246);"><span><span><span><span class="keyword" style="font-weight: bold;">public</span> </span><span class="keyword" style="font-weight: bold;">void</span> scalarQuery(){ Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); String sql = </span><span class="string" style="color:#dd1144;">"select * from person_inf"</span>; List list = session.createSQLQuery(sql). addScalar(</span><span class="string" style="color:#dd1144;">"person_id"</span>,StandardBasicTypes.INTEGER). addScalar(<span class="string" style="color:#dd1144;">"name"</span>, StandardBasicTypes.STRING). addScalar(<span class="string" style="color:#dd1144;">"age"</span>,StandardBasicTypes.INTEGER).list(); <span class="keyword" style="font-weight: bold;">for</span>(Iterator iterator = list.iterator();iterator.hasNext();){ <span class="comment" style="color:#999988;font-style: italic;">//每個集合元素都是一個數組,陣列元素師person_id,person_name,person_age三列值 </span> Object[] objects = (Object[]) iterator.next(); System.<span class="keyword" style="font-weight: bold;">out</span>.println(<span class="string" style="color:#dd1144;">"id="</span>+objects[<span class="number" style="color:#09999;">0</span>]); System.<span class="keyword" style="font-weight: bold;">out</span>.println(<span class="string" style="color:#dd1144;">"name="</span>+objects[<span class="number" style="color:#09999;">1</span>]); System.<span class="keyword" style="font-weight: bold;">out</span>.println(<span class="string" style="color:#dd1144;">"age="</span>+objects[<span class="number" style="color:#09999;">2</span>]); System.<span class="keyword" style="font-weight: bold;">out</span>.println(<span class="string" style="color:#dd1144;">"----------------------------"</span></span>); } tx.commit(); session.close(); }</span></font>
從上面可以看出。標量查詢中addScalar()方法有兩個作用:
1、指定查詢結果包含哪些資料列---沒有被addScalar選出的列將不會包含在查詢結果中。
2、指定查詢結果中資料列的資料型別
二、實體查詢
上面的標量查詢返回的標量結果集,也就是從resultset中返回的“裸”資料。如果我們想要的結果是某個物件的實體,這是就可以通過addEntity()方法來實現。addEntity()方法可以講結果轉換為實體。但是在轉換的過程中要注意幾個問題:
1、查詢返回的是某個資料表的全部資料列
2、該資料表有對應的持久化類對映
這時才可以通過addEntity()方法將查詢結果轉換成實體。
<span style="font-family:SimSun;"><span style="font-size:12px;">session.createSQLQuery("<span class="operator"><span style="background-color: rgb(246, 246, 246);"><span class="keyword" style="font-weight: bold;">select</span> * <span class="keyword" style="font-weight: bold;">from</span> perons_inf<span class="string" style="color:#dd1144;">").addEntity(Person.class).list();
session.createSQLQuery("</span><span class="keyword" style="font-weight: bold;">select</span> id,name,age <span class="keyword" style="font-weight: bold;">from</span> person_inf<span class="string" style="color:#dd1144;">").addEntity(Person.class).list();</span></span></span></span></span>
這個查詢指定:
1、SQL查詢字串
2、要返回的實體
假設Person被對映為擁有id,name和age三個欄位的類,以上的兩個查詢都返回一個List,每個元素都是一個Person實體。
假若實體在對映時有一個many-to-one的關聯指向另外一個實體,在查詢時必須也返回那個實體(獲取對映的外來鍵列),否則會導致發生一個"column not found"的資料庫錯誤。這些附加的欄位可以使用*標註來自動返回,但我們希望還是明確指明,看下面這個具有指向teacher的many-to-one的例子:
<span style="font-family:SimSun;"><span style="font-size:12px;">sess.createSQLQuery("<span class="operator"><span style="background-color: rgb(246, 246, 246);"><span class="keyword" style="font-weight: bold;">select</span> id, name, age, teacherID <span class="keyword" style="font-weight: bold;">from</span> person_inf<span class="string" style="color:#dd1144;">").addEntity(Person.class).list();</span></span></span></span></span>
這樣就可以通過person.getTeacher()獲得teacher了。
例項:
<font face="SimSun"><span style="font-size:12px;"><span style="background-color: rgb(246, 246, 246);"><span><span><span><span class="keyword" style="font-weight: bold;">public</span> </span><span class="keyword" style="font-weight: bold;">void</span> entityQuery(){
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
String sql = </span><span class="string" style="color:#dd1144;">"select * from person_inf"</span>;
List </span><span class="built_in" style="color:#086b3;">list</span> = session.createSQLQuery(sql).
addEntity(Person.<span class="keyword" style="font-weight: bold;">class</span>). <span class="comment" style="color:#999988;font-style: italic;">//指定將查詢的記錄行轉換成Person實體 </span>
<span class="built_in" style="color:#086b3;">list</span>();
<span class="keyword" style="font-weight: bold;">for</span> (Iterator iterator = <span class="built_in" style="color:#086b3;">list</span>.iterator();iterator.hasNext();) {
Person person = (Person) iterator.next(); <span class="comment" style="color:#999988;font-style: italic;">//集合的每個元素都是一個Person物件 </span>
System.out.println(<span class="string" style="color:#dd1144;">"name="</span>+person.getName());
System.out.println(<span class="string" style="color:#dd1144;">"age="</span></span>+person.getAge());
}
tx.commit();
session.close();
}</span></font>
上面的都是單表查詢,如果我們在SQL語句中使用了多表連線,則SQL語句可以選出多個數據表的資料。Hibernate支援將查詢結果轉換成多個實體。如果要將查詢結果轉換成多個實體,則SQL字串中應該為不同資料表指定不同別名,並且呼叫addEntity()方法將不同資料錶轉換成不同實體。如下
<font face="SimSun"><span style="font-size:12px;"><span style="background-color: rgb(246, 246, 246);"><span><span><span><span class="keyword" style="font-weight: bold;">public</span> </span><span class="keyword" style="font-weight: bold;">void</span> multiEntityQuery(){ Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); String sql = </span><span class="string" style="color:#dd1144;">"select p.*,e.* from person_inf as p inner join event_inf as e"</span> + </span><span class="string" style="color:#dd1144;">" on p.person_id=e.person_id"</span>; List list = session.createSQLQuery(sql) .addEntity(<span class="string" style="color:#dd1144;">"p"</span>,Person.<span class="keyword" style="font-weight: bold;">class</span>) .addEntity(<span class="string" style="color:#dd1144;">"e"</span>, MyEvent.<span class="keyword" style="font-weight: bold;">class</span>) .list(); <span class="keyword" style="font-weight: bold;">for</span>(Iterator iterator = list.iterator();iterator.hasNext();){ <span class="comment" style="color:#999988;font-style: italic;">//每個集合元素都是Person、MyEvent所組成的陣列 </span> Object[] objects = (Object[]) iterator.next(); Person person = (Person) objects[<span class="number" style="color:#09999;">0</span>]; MyEvent <span class="keyword" style="font-weight: bold;">event</span> = (MyEvent) objects[<span class="number" style="color:#09999;">1</span>]; System.<span class="keyword" style="font-weight: bold;">out</span>.println(<span class="string" style="color:#dd1144;">"person_id="</span>+person.getId()+<span class="string" style="color:#dd1144;">" person_name="</span>+person.getName()+<span class="string" style="color:#dd1144;">" title="</span>+<span class="keyword" style="font-weight: bold;">event</span></span>.getTitle()); } }</span></font>
三、處理關聯和繼承
通過提前抓取將Event連接獲得,而避免初始化proxy帶來的額外開銷也是可能的。這是通過addJoin()方法進行的,通過這個方法可以講實體的關聯實體轉換成查詢物件。如下:
<font face="SimSun"><span style="font-size:12px;"><span style="background-color: rgb(246, 246, 246);"><span><span><span><span class="keyword" style="font-weight: bold;">public</span> </span><span class="keyword" style="font-weight: bold;">void</span> joinQuery(){ Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); String sql = </span><span class="string" style="color:#dd1144;">"select p.*,e.* from person_inf as p,event_inf as e where e.person_id=p.person_id"</span>; List list = session.createSQLQuery(sql) .addEntity(</span><span class="string" style="color:#dd1144;">"p"</span>,Person.<span class="keyword" style="font-weight: bold;">class</span>) .addJoin(<span class="string" style="color:#dd1144;">"e"</span>,<span class="string" style="color:#dd1144;">"p.myEvents"</span>) .list(); <span class="keyword" style="font-weight: bold;">for</span>(Iterator iterator = list.iterator();iterator.hasNext();){ <span class="comment" style="color:#999988;font-style: italic;">//每個集合元素都是Person、MyEvent所組成的陣列 </span> Object[] objects = (Object[]) iterator.next(); Person person = (Person) objects[<span class="number" style="color:#09999;">0</span>]; MyEvent <span class="keyword" style="font-weight: bold;">event</span> = (MyEvent) objects[<span class="number" style="color:#09999;">1</span>]; System.<span class="keyword" style="font-weight: bold;">out</span>.println(<span class="string" style="color:#dd1144;">"person_id="</span>+person.getId()+<span class="string" style="color:#dd1144;">" person_name="</span>+person.getName()+<span class="string" style="color:#dd1144;">" title="</span>+<span class="keyword" style="font-weight: bold;">event</span></span>.getTitle()); } }</span></font>上面的程式返回的Person物件,其屬性myEvent屬性已經完全被初始化,不再需要資料庫的額外操作,同時將該屬性轉換成別名為e的實體。也就是說返回的結果是Person、Event物件陣列的列表。
四、命名查詢
我們可以將SQL語句不放在程式中,而是放在配置檔案中。這樣可以更好地提高程式解耦。
Hibernate使用<sql-query.../>元素來配置命名SQL查詢,配置<sql-query.../>元素有一個必填的name屬性,該屬性用於指定該命名SQL查詢的名稱。
使用<sql-query.../>元素定義命名查詢時,可以包含如下幾個元素:
<return.../>:將查詢結果轉換成持久化實體
<return-join.../>:預載入持久化實體的關聯實體
<return-scalar.../>:將查詢的資料列轉換成標量值
在使用命名SQL查詢時,不需要呼叫addEntity()、addScalar()等方法。因為在配置命名SQL查詢時,已經指定了查詢返回的結果資訊。
[html] view plaincopyprint?
<!-- 命名SQL查詢 -->
<font style="background-color: rgb(246, 246, 246);"><font face="SimSun"><span style="font-size:12px;"><span><span><span><span class="tag" style="color:#0080;"><<span class="title">sql-query</span> <span class="attribute" style="color:#08080;">name</span>=<span class="value" style="color:#dd1144;">"sqlquery"</span>></span> </span><span class="comment" style="color:#999988;font-style: italic;"><!-- 將p別名轉換為Person實體 --></span> </span><span class="tag" style="color:#0080;"><<span class="title">return</span> <span class="attribute" style="color:#08080;">alias</span>=<span class="value" style="color:#dd1144;">"p"</span> <span class="attribute" style="color:#08080;">class</span>=<span class="value" style="color:#dd1144;">"Person"</span> /></span> </span><span class="comment" style="color:#999988;font-style: italic;"><!-- 將e別名轉換成Event實體 --></span> <span class="tag" style="color:#0080;"><<span class="title">return</span> <span class="attribute" style="color:#08080;">alias</span>=<span class="value" style="color:#dd1144;">"e"</span> <span class="attribute" style="color:#08080;">class</span>=<span class="value" style="color:#dd1144;">"MyEvent"</span> /></span> <span class="comment" style="color:#999988;font-style: italic;"><!-- 指定將person_inf表的name屬性列作為標量值返回--></span> <span class="tag" style="color:#0080;"><<span class="title">return-scalar</span> <span class="attribute" style="color:#08080;">column</span>=<span class="value" style="color:#dd1144;">"p.name"</span> <span class="attribute" style="color:#08080;">type</span>=<span class="value" style="color:#dd1144;">"string"</span>/></span> select p.*,e.* from person_inf as p,event_inf as e where p.person_id = e.person_id and p.age=:age <span class="tag" style="color:#0080;"></<span class="title">sql-query</span>></span> 使用Session的getNamedQuery即可獲得指定命名sql查詢。 [java] view plaincopyprint? public void query(){ Session session = HibernateUtil.getSession(); //呼叫命名查詢,直接返回結果 List list = session.getNamedQuery("sqlquery") .setInteger("age", 30).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()); } session.close(); } Hibernate允許吧把結果集的對映資訊放在<span class="tag" style="color:#0080;"><<span class="title">resultset...</span>/></span>元素定義,這樣就可讓多個命名查詢共有該結果集對映。 [html] view plaincopyprint? <span class="tag" style="color:#0080;"><<span class="title">resultset</span> <span class="attribute" style="color:#08080;">name</span>=<span class="value" style="color:#dd1144;">"person_resultSet"</span>></span> <span class="tag" style="color:#0080;"><<span class="title">return</span> <span class="attribute" style="color:#08080;">alias</span>=<span class="value" style="color:#dd1144;">"p"</span> <span class="attribute" style="color:#08080;">class</span>=<span class="value" style="color:#dd1144;">"Person"</span> /></span> <span class="tag" style="color:#0080;"><<span class="title">return-scalar</span> <span class="attribute" style="color:#08080;">column</span>=<span class="value" style="color:#dd1144;">"p.age"</span> <span class="attribute" style="color:#08080;">type</span>=<span class="value" style="color:#dd1144;">"int"</span>/></span> <span class="tag" style="color:#0080;"></<span class="title">resultset</span>></span> 通過為<span class="tag" style="color:#0080;"><<span class="title">sql-query...</span>/></span>元素指定resultset-ref屬性,就可以讓命名SQL查詢使用一個已有的結果集映射了。 [html] view plaincopyprint? <span class="tag" style="color:#0080;"><<span class="title">sql-query</span> <span class="attribute" style="color:#08080;">name</span>=<span class="value" style="color:#dd1144;">"sqlquery"</span> <span class="attribute" style="color:#08080;">resultset-ref</span>=<span class="value" style="color:#dd1144;">"person_resultSet"</span>></span> select p.* from person as p <span class="tag" style="color:#0080;"></<span class="title">sql-query</span>></span></span></font></font>
五、呼叫儲存過程
Hibernate可以通過命名SQL查詢來呼叫儲存過程或者函式。對於函式,該函式必須返回一個結果集;對於儲存過程,該儲存過程的第一個引數必須傳出引數,且資料型別是結果集。
下面是一個簡單的儲存過程:
<span class="operator"><span style="background-color: rgb(246, 246, 246);"><span style="font-family:SimSun;"><span style="font-size:12px;"><span class="keyword" style="font-weight: bold;">Create</span> <span class="keyword" style="font-weight: bold;">procedure</span> select_person()
ect * <span class="keyword" style="font-weight: bold;">from</span> person_inf;</span></span></span></span>
如果需要使用該儲存過程,可以先將其定義成命名SQL查詢,然後在程式中使用。
當使用原生SQL來呼叫儲存過程,應該為<sql-query.../>元素指定callable="true"。
<font style="background-color: rgb(246, 246, 246);"><font face="SimSun"><span style="font-size:12px;"><span><span><span><span class="tag" style="color:#0080;"><<span class="title">sql-query</span> <span class="attribute" style="color:#08080;">name</span>=<span class="value" style="color:#dd1144;">"callProcedure"</span> <span class="attribute" style="color:#08080;">callable</span>=<span class="value" style="color:#dd1144;">"true"</span>></span> </span><span class="tag" style="color:#0080;"><<span class="title">return</span> <span class="attribute" style="color:#08080;">class</span>=<span class="value" style="color:#dd1144;">"Person"</span>></span> </span><span class="comment" style="color:#999988;font-style: italic;"><!-- 將查詢的資料列轉換成實體的屬性 --></span> </span><span class="tag" style="color:#0080;"><<span class="title">return-property</span> <span class="attribute" style="color:#08080;">name</span>=<span class="value" style="color:#dd1144;">"name"</span> <span class="attribute" style="color:#08080;">column</span>=<span class="value" style="color:#dd1144;">"name"</span>/></span> <span class="tag" style="color:#0080;"><<span class="title">return-property</span> <span class="attribute" style="color:#08080;">name</span>=<span class="value" style="color:#dd1144;">"age"</span> <span class="attribute" style="color:#08080;">column</span>=<span class="value" style="color:#dd1144;">"age"</span> /></span> <span class="tag" style="color:#0080;"><<span class="title">return-property</span> <span class="attribute" style="color:#08080;">name</span>=<span class="value" style="color:#dd1144;">"person_id"</span> <span class="attribute" style="color:#08080;">column</span>=<span class="value" style="color:#dd1144;">"id"</span> /></span> <span class="tag" style="color:#0080;"></<span class="title">return</span>></span> <span class="tag" style="color:#0080;"></<span class="title">sql-query</span>></span></span></font></font>
程式與上面相同。
呼叫儲存過程需要注意以下幾個問題:
為了在Hibernate中使用儲存過程,你必須遵循一些規則.不遵循這些規則的儲存過程將不可用.如果你仍然想要使用他們, 你必須通過session.connection()來執行他們.這些規則針對於不同的資料庫.因為資料庫 提供商有各種不同的儲存過程語法和語義.
對儲存過程進行的查詢無法使用setFirstResult()/setMaxResults()進行分頁。
建議採用的呼叫方式是標準SQL92: { ? = call functionName(<parameters>) } 或者 { ? = call procedureName(<parameters>}.原生呼叫語法不被支援。
對於Oracle有如下規則:
函式必須返回一個結果集。儲存過程的第一個引數必須是OUT,它返回一個結果集。這是通過Oracle 9或10的SYS_REFCURSOR型別來完成的。在Oracle中你需要定義一個REF CURSOR型別,參見Oracle的手冊。
對於Sybase或者MS SQL server有如下規則:
儲存過程必須返回一個結果集。.注意這些servers可能返回多個結果集以及更新的數目.Hibernate將取出第一條結果集作為它的返回值, 其他將被丟棄。