Hibernate SQLQuery 原生SQL 查詢及返回結果集處理-1

來源:互聯網
上載者:User

標籤:des   style   blog   http   io   color   ar   os   使用   

第一篇:官方文檔的處理方法,摘自官方


在遷移原先用JDBC/SQL實現的系統,難免需要採用hibernat native sql支援。
1.使用SQLQuery
hibernate對原生SQL查詢執行的控制是通過SQLQuery介面進行的.

Session.createSQLQuery();1.1標量查詢
最基本的SQL查詢就是獲得一個標量(數值)的列表。
sess.createSQLQuery("SELECT * FROM CATS").list();
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
將返回一個Object數組(Object[])組成的List,數組每個元素都是CATS表的一個欄位值。Hibernate會使用ResultSetMetadata來判定返回的標量值的實際順序和類型。

如果要避免過多的使用ResultSetMetadata,或者只是為了更加明確的指名傳回值,可以使用addScalar()。

sess.createSQLQuery("SELECT * FROM CATS")
.addScalar("ID", Hibernate.LONG)
.addScalar("NAME", Hibernate.STRING)
.addScalar("BIRTHDATE", Hibernate.DATE)

這個查詢指定了:SQL查詢字串,要返回的欄位和類型.它仍然會返回Object數組,但是此時不再使用ResultSetMetdata,而是明確的將ID,NAME和BIRTHDATE按照Long, String和Short類型從resultset中取出。同時,也指明了就算query是使用*來查詢的,可能獲得超過列出的這三個欄位,也僅僅會返回這三個欄位。

對全部或者部分的標量值不設定類型資訊也是可以的。

sess.createSQLQuery("SELECT * FROM CATS")
.addScalar("ID", Hibernate.LONG)
.addScalar("NAME")
.addScalar("BIRTHDATE")

基本上這和前面一個查詢相同,只是此時使用ResultSetMetaData來決定NAME和BIRTHDATE的類型,而ID的類型是明確指出的。

關於從ResultSetMetaData返回的java.sql.Types是如何映射到Hibernate類型,是由方言(Dialect)控制的。假若某個指定的類型沒有被映射,或者不是你所預期的類型,你可以通過Dialet的registerHibernateType調用自行定義.
1.2 實體查詢
上面的查詢都是返回標量值的,也就是從resultset中返回的“裸”資料。下面展示如何通過addEntity()讓原生查詢返回實體物件。

sess.createSQLQuery("SELECT * FROM CATS").addEntity(Cat.class);
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class);

這個查詢指定:SQL查詢字串,要返回的實體.假設Cat被映射為擁有ID,NAME和BIRTHDATE三個欄位的類,以上的兩個查詢都返回一個List,每個元素都是一個Cat實體。

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

sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, DOG_ID FROM CATS").addEntity(Cat.class);這樣cat.getDog()就能正常運行。 
1.3 處理關聯和集合類
通過提前抓取將Dog串連獲得,而避免初始化proxy帶來的額外開銷也是可能的。這是通過addJoin()方法進行的,這個方法可以讓你將關聯或集合串連進來。
sess.createSQLQuery("SELECT c.ID, NAME, BIRTHDATE, DOG_ID, D_ID, D_NAME FROM CATS c, DOGS d WHERE c.DOG_ID = d.D_ID")
.addEntity("cat", Cat.class)
.addJoin("cat.dog");

上面這個例子中,返回的Cat對象,其dog屬性被完全初始化了,不再需要資料庫的額外操作。注意,我們加了一個別名("cat"),以便指明join的目標屬性路徑。通過同樣的提前串連也可以作用於集合類,例如,假若Cat有一個指向Dog的一對多關聯。
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, D_ID, D_NAME, CAT_ID FROM CATS c, DOGS d WHERE c.ID = d.CAT_ID")
.addEntity("cat", Cat.class)
.addJoin("cat.dogs");

1.4 返回多個實體

到目前為止,結果集欄位名被假定為和對應檔中指定的的欄位名是一致的。假若SQL查詢串連了多個表,同一個欄位名可能在多個表中出現多次,這就會造成問題。

下面的查詢中需要使用欄位別名注射(這個例子本身會失敗):

sess.createSQLQuery("SELECT c.*, m.*   FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
.addEntity("cat", Cat.class)
.addEntity("mother", Cat.class)

這個查詢的本意是希望每行返回兩個Cat執行個體,一個是cat,另一個是它的媽媽。但是因為它們的欄位名被映射為相同的,而且在某些資料庫中,返回的欄位別名是“c.ID”,"c.NAME"這樣的形式,而它們和在對應檔中的名字("ID"和"NAME")不匹配,這就會造成失敗。

下面的形式可以解決欄位名重複:

sess.createSQLQuery("SELECT {cat.*}, {mother.*}   FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
.addEntity("cat", Cat.class)
.addEntity("mother", Cat.class)

這個查詢指明:SQL查詢語句,其中包含佔位附來讓Hibernate注射欄位別名,查詢返回的實體

上面使用的{cat.*}和{mother.*}標記是作為“所有屬性”的簡寫形式出現的。當然你也可以明確地羅列出欄位名,但在這個例子裡面我們讓Hibernate來為每個屬性注射SQL欄位別名。欄位別名的預留位置是屬性名稱加上表別名的首碼。在下面的例子中,我們從另外一個表(cat_log)中通過映射中繼資料中的指定擷取Cat和它的媽媽。注意,要是我們願意,我們甚至可以在where子句中使用屬性別名。

String sql = "SELECT ID as {c.id}, NAME as {c.name}, " + 
      "BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
      "FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";

List loggedCats = sess.createSQLQuery(sql)
      .addEntity("cat", Cat.class)
      .addEntity("mother", Cat.class).list();
1.4.1 別名和屬性引用

大多數情況下,都需要上面的屬性注射,但在使用更加複雜的映射,比如複合屬性、通過標識符構造繼承樹,以及集合類等等情況下,也有一些特別的別名,來允許Hibernate注射合適的別名。

 

下表列出了使用別名注射參數的不同可能性。注意:下面結果中的別名只是樣本,實用時每個別名需要唯一併且不同的名字。


 

1.5. 返回非受管實體
可以對原生SQL 查詢使用ResultTransformer。這會返回不受Hibernate管理的實體。

sess.createSQLQuery("SELECT NAME, BIRTHDATE FROM CATS")
       .setResultTransformer(Transformers.aliasToBean(CatDTO.class))

這個查詢指定:SQL查詢字串,結果轉換器(result transformer)

上面的查詢將會返回CatDTO的列表,它將被執行個體化並且將NAME和BIRTHDAY的值注射入對應的屬性或者欄位。

 

轉自 http://blog.csdn.net/yangqicong/article/details/6910740

 

Hibernate SQLQuery 原生SQL 查詢及返回結果集處理-1

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.