今天沒事的時候,看到公司框架裏有一個用原生SQL寫的函數,說實在之前本身也幹過這事,但很久都沒有用,都忘得差很少了,如今基本都是用的hql語句來查詢結果。hibernate中使用createSQLQuery拉來來實現SQL語句的查詢,具體用法:session.createSQLQuery(sql),對於用SQL返回的結果集是一個什麼樣的結果集都毫無記憶。本身查了下,才知道,原來是返回一個Object類型數組的list集合,而其中Object類型的數組裏的值則與sql語句中的查詢項相對應,若是是select * from XXX ,則數組值就是按照XXX表中的全部字段來一一對應。其它很少說,在網上看到一篇文章裏面講得很細,就直接轉過來了:
在遷移原先用JDBC/SQL實現的系統,不免須要採用hibernat native sql支持。
1.使用SQLQuery
hibernate對原生SQL查詢執行的控制是經過SQLQuery接口進行的.java
1.1標量查詢
最基本的SQL查詢就是得到一個標量(數值)的列表。sql
將返回一個Object數組(Object[])組成的List,數組每一個元素都是CATS表的一個字段值。Hibernate會使用ResultSetMetadata來斷定返回的標量值的實際順序和類型。數據庫
若是要避免過多的使用ResultSetMetadata,或者只是爲了更加明確的指名返回值,可使用addScalar()。數組
這個查詢指定了:SQL查詢字符串,要返回的字段和類型.它仍然會返回Object數組,可是此時再也不使用ResultSetMetdata,而是明確的 將ID,NAME和BIRTHDATE按照Long, String和Short類型從resultset中取出。同時,也指明瞭就算query是使用*來查詢的,可能得到超過列出的這三個字段,也僅僅會返回 這三個字段。session
對所有或者部分的標量值不設置類型信息也是能夠的。框架
基本上這和前面一個查詢相同,只是此時使用ResultSetMetaData來決定NAME和BIRTHDATE的類型,而ID的類型是明確指出的。函數
關於從ResultSetMetaData返回的java.sql.Types是如何映射到Hibernate類型,是由方言(Dialect)控制的。倘若某個指定的類型沒有被映射,或者不是你所預期的類型,你能夠經過Dialet的registerHibernateType調用自行定義.
1.2 實體查詢
上面的查詢都是返回標量值的,也就是從resultset中返回的「裸」數據。下面展現如何經過addEntity()讓原生查詢返回實體對象。spa
這個查詢指定:SQL查詢字符串,要返回的實體.假設Cat被映射爲擁有ID,NAME和BIRTHDATE三個字段的類,以上的兩個查詢都返回一個List,每一個元素都是一個Cat實體。.net
倘若實體在映射時有一個many-to-one的關聯指向另一個實體,在查詢時必須也返回那個實體,不然會致使發生一個"column not found"的數據庫錯誤。這些附加的字段可使用*標註來自動返回,但咱們但願仍是明確指明,看下面這個具備指向Dog的many-to-one的例 子:hibernate
這樣cat.getDog()就能正常運行。
1.3 處理關聯和集合類
經過提早抓取將Dog鏈接得到,而避免初始化proxy帶來的額外開銷也是可能的。這是經過addJoin()方法進行的,這個方法可讓你將關聯或集合鏈接進來。
上面這個例子中,返回的Cat對象,其dog屬性被徹底初始化了,再也不須要數據庫的額外操做。注意,咱們加了一個別名("cat"),以便指明join的目標屬性路徑。經過一樣的提早鏈接也能夠做用於集合類,例如,倘若Cat有一個指向Dog的一對多關聯。
1.4 返回多個實體
到目前爲止,結果集字段名被假定爲和映射文件中指定的的字段名是一致的。倘若SQL查詢鏈接了多個表,同一個字段名可能在多個表中出現屢次,這就會形成問題。
下面的查詢中須要使用字段別名注射(這個例子自己會失敗):
這個查詢的本意是但願每行返回兩個Cat實例,一個是cat,另外一個是它的媽媽。可是由於它們的字段名被映射爲相同的,並且在某些數據庫中,返回的字段別 名是「c.ID」,"c.NAME"這樣的形式,而它們和在映射文件中的名字("ID"和"NAME")不匹配,這就會形成失敗。
下面的形式能夠解決字段名重複:
這個查詢指明:SQL查詢語句,其中包含佔位附來讓Hibernate注射字段別名,查詢返回的實體
上面使用的{cat.*}和{mother.*}標記是做爲「全部屬性」的簡寫形式出現的。固然你也能夠明確地羅列出字段名,但在這個例子裏面咱們讓 Hibernate來爲每一個屬性注射SQL字段別名。字段別名的佔位符是屬性名加上表別名的前綴。在下面的例子中,咱們從另一個表(cat_log)中 經過映射元數據中的指定獲取Cat和它的媽媽。注意,要是咱們願意,咱們甚至能夠在where子句中使用屬性別名。
1.4.1 別名和屬性引用
大多數狀況下,都須要上面的屬性注射,但在使用更加複雜的映射,好比複合屬性、經過標識符構造繼承樹,以及集合類等等狀況下,也有一些特別的別名,來容許Hibernate注射合適的別名。
下表列出了使用別名注射參數的不一樣可能性。注意:下面結果中的別名只是示例,實用時每一個別名須要惟一而且不一樣的名字。
別名注射(alias injection names)
描述 | 語法 | 示例 | |
---|---|---|---|
簡單屬性 | {[aliasname].[propertyname] | A_NAME as {item.name} | |
複合屬性 | {[aliasname].[componentname].[propertyname]} | CURRENCY as {item.amount.currency}, VALUE as {item.amount.value} | |
實體辨別器(Discriminator of an entity) | {[aliasname].class} | DISC as {item.class} | |
實體的全部屬性 | {[aliasname].*} | {item.*} | |
集合鍵(collection key) | {[aliasname].key} | ORGID as {coll.key} | |
集合id | {[aliasname].id} | EMPID as {coll.id} | |
集合元素 | {[aliasname].element} | XID as {coll.element} | |
集合元素的屬性 | {[aliasname].element.[propertyname]} | NAME as {coll.element.name} | |
集合元素的全部屬性 | {[aliasname].element.*} | {coll.element.*} | |
集合的全部屬性 | {[aliasname].*} | {coll.*} |
1.5. 返回非受管實體
能夠對原生sql 查詢使用ResultTransformer。這會返回不受Hibernate管理的實體。
這個查詢指定:SQL查詢字符串,結果轉換器(result transformer)
上面的查詢將會返回CatDTO的列表,它將被實例化而且將NAME和BIRTHDAY的值注射入對應的屬性或者字段。
轉自:http://blog.csdn.net/yangqicong/article/details/6910740