<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    You smiled and talked to me of nothing and I felt that for this I had been waiting long.

    The trees come up to my window like the yearning voice of the dumb earth.

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      19 Posts :: 10 Stories :: 25 Comments :: 0 Trackbacks

    在遷移原先用JDBC/SQL實現(xiàn)的系統(tǒng),難免需要采用hibernat native sql支持。
    1.使用SQLQuery
    hibernate對原生SQL查詢執(zhí)行的控制是通過SQLQuery接口進行的.

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

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

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

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

    對全部或者部分的標量值不設置類型信息也是可以的。

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

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

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

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

    這個查詢指定:SQL查詢字符串,要返回的實體.假設Cat被映射為擁有ID,NAME和BIRTHDATE三個字段的類,以上的兩個查詢都返回一個List,每個元素都是一個Cat實體。 假若實體在映射時有一個many-to-one的關聯(lián)指向另外一個實體,在查詢時必須也返回那個實體,否則會導致發(fā)生一個"column not found"的數(shù)據(jù)庫錯誤。這些附加的字段可以使用*標注來自動返回,但我們希望還是明確指明,看下面這個具有指向Dog的many-to-one的例子:

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

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

    1.4 返回多個實體

    到目前為止,結果集字段名被假定為和映射文件中指定的的字段名是一致的。假若SQL查詢連接了多個表,同一個字段名可能在多個表中出現(xiàn)多次,這就會造成問題。

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

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

    這個查詢的本意是希望每行返回兩個Cat實例,一個是cat,另一個是它的媽媽。但是因為它們的字段名被映射為相同的,而且在某些數(shù)據(jù)庫中,返回的字段別名是“c.ID”,"c.NAME"這樣的形式,而它們和在映射文件中的名字("ID"和"NAME")不匹配,這就會造成失敗。

    下面的形式可以解決字段名重復:

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

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

    上面使用的{cat.*}和{mother.*}標記是作為“所有屬性”的簡寫形式出現(xiàn)的。當然你也可以明確地羅列出字段名,但在這個例子里面我們讓Hibernate來為每個屬性注射SQL字段別名。字段別名的占位符是屬性名加上表別名的前綴。在下面的例子中,我們從另外一個表(cat_log)中通過映射元數(shù)據(jù)中的指定獲取Cat和它的媽媽。注意,要是我們愿意,我們甚至可以在where子句中使用屬性別名

    1String sql = "SELECT ID as {c.id}, NAME as {c.name}, " + 
    2         "BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
    3         "FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";
    4
    5List loggedCats = sess.createSQLQuery(sql)
    6        .addEntity("cat", Cat.class)
    7        .addEntity("mother", Cat.class).list();
    1.4.1 別名和屬性引用

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

    下表列出了使用別名注射參數(shù)的不同可能性。注意:下面結果中的別名只是示例,實用時每個別名需要唯一并且不同的名字

    別名注射(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管理的實體。
    1sess.createSQLQuery("SELECT NAME, BIRTHDATE FROM CATS")
    2        .setResultTransformer(Transformers.aliasToBean(CatDTO.class))

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

    上面的查詢將會返回CatDTO的列表,它將被實例化并且將NAME和BIRTHDAY的值注射入對應的屬性或者字段。

    1.6. 處理繼承
    原生SQL查詢假若其查詢結果實體是繼承樹中的一部分,它必須包含基類和所有子類的所有屬性。
    1.7. 參數(shù)
    原生查詢支持位置參數(shù)和命名參數(shù)
    1Query query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like ?").addEntity(Cat.class);
    2List pusList = query.setString(0"Pus%").list();
    3     
    4query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like :name").addEntity(Cat.class);
    5List pusList = query.setString("name""Pus%").list(); 
    2.使用命名SQL查詢
    可以在映射文檔中定義查詢的名字,然后就可以象調用一個命名的HQL查詢一樣直接調用命名SQL查詢.在這種情況下,不需要調用addEntity()方法.
    1 <sql-query name="persons">
    2     <return alias="person" class="eg.Person"/>
    3     SELECT person.NAME AS {person.name},
    4            person.AGE AS {person.age},
    5            person.SEX AS {person.sex}
    6     FROM PERSON person
    7     WHERE person.NAME LIKE :namePattern
    8 </sql-query>

    1List people = sess.getNamedQuery("persons")
    2    .setString("namePattern", namePattern)
    3    .setMaxResults(50)
    4    .list();
    <return-join><load-collection> 元素是用來連接關聯(lián)以及將查詢定義為預先初始化各個集合的。
     1 <sql-query name="personsWith">
     2     <return alias="person" class="eg.Person"/>
     3     <return-join alias="address" property="person.mailingAddress"/>
     4     SELECT person.NAME AS {person.name},
     5            person.AGE AS {person.age},
     6            person.SEX AS {person.sex},
     7            adddress.STREET AS {address.street},
     8            adddress.CITY AS {address.city},
     9            adddress.STATE AS {address.state},
    10            adddress.ZIP AS {address.zip}
    11     FROM PERSON person
    12     JOIN ADDRESS adddress
    13         ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
    14     WHERE person.NAME LIKE :namePattern
    15 </sql-query>
    一個命名查詢可能會返回一個標量值.你必須使用<return-scalar>元素來指定字段的別名和 Hibernate類型
    1<sql-query name="mySqlQuery">
    2    <return-scalar column="name" type="string"/>
    3    <return-scalar column="age" type="long"/>
    4    SELECT p.NAME AS name,
    5           p.AGE AS age,
    6    FROM PERSON p WHERE p.NAME LIKE 'Hiber%'
    7</sql-query>
    可以把結果集映射的信息放在外部的<resultset>元素中,這樣就可以在多個命名查詢間,或者通過setResultSetMapping()API來訪問
     1 <resultset name="personAddress">
     2     <return alias="person" class="eg.Person"/>
     3     <return-join alias="address" property="person.mailingAddress"/>
     4 </resultset>
     5 
     6 <sql-query name="personsWith" resultset-ref="personAddress">
     7     SELECT person.NAME AS {person.name},
     8            person.AGE AS {person.age},
     9            person.SEX AS {person.sex},
    10            adddress.STREET AS {address.street},
    11            adddress.CITY AS {address.city},
    12            adddress.STATE AS {address.state},
    13            adddress.ZIP AS {address.zip}
    14     FROM PERSON person
    15     JOIN ADDRESS adddress
    16         ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
    17     WHERE person.NAME LIKE :namePattern
    18 </sql-query>
    另外,你可以在java代碼中直接使用hbm文件中的結果集定義信息。
    1 List cats = sess.createSQLQuery(
    2         "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
    3     )
    4     .setResultSetMapping("catAndKitten")
    5     .list();
    2.1. 使用return-property來明確地指定字段/別名
    使用<return-property>你可以明確的告訴Hibernate使用哪些字段別名,這取代了使用{}-語法 來讓Hibernate注入它自己的別名.
     1<sql-query name="mySqlQuery">
     2    <return alias="person" class="eg.Person">
     3      <return-property name="name" column="myName"/>
     4      <return-property name="age" column="myAge"/>
     5      <return-property name="sex" column="mySex"/>
     6    </return>
     7    SELECT person.NAME AS myName,
     8           person.AGE AS myAge,
     9           person.SEX AS mySex,
    10    FROM PERSON person WHERE person.NAME LIKE :name
    11</sql-query>
    <return-property>也可用于多個字段,它解決了使用{}-語法不能細粒度控制多個字段的限制
     1 <sql-query name="organizationCurrentEmployments">
     2             <return alias="emp" class="Employment">            
     3              <return-property name="salary"> 
     4                <return-column name="VALUE"/>
     5                <return-column name="CURRENCY"/>            
     6              </return-property>
     7              <return-property name="endDate" column="myEndDate"/>
     8             </return>
     9             SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer}, 
    10             STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
    11             REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY
    12             FROM EMPLOYMENT
    13             WHERE EMPLOYER = :id AND ENDDATE IS NULL
    14             ORDER BY STARTDATE ASC
    15 </sql-query>

    如果你映射一個識別器(discriminator),你必須使用<return-discriminator> 來指定識別器字段
    2.2. 使用存儲過程來查詢
    Hibernate 3引入了對存儲過程查詢(stored procedure)和函數(shù)(function)的支持.以下的說明中,這二者一般都適用。 存儲過程/函數(shù)必須返回一個結果集,作為Hibernate能夠使用的第一個外部參數(shù).

     1 <sql-query name="selectAllEmployees_SP" callable="true">
     2     <return alias="emp" class="Employment">
     3         <return-property name="employee" column="EMPLOYEE"/>
     4         <return-property name="employer" column="EMPLOYER"/>            
     5         <return-property name="startDate" column="STARTDATE"/>
     6         <return-property name="endDate" column="ENDDATE"/>            
     7         <return-property name="regionCode" column="REGIONCODE"/>            
     8         <return-property name="id" column="EID"/>                        
     9         <return-property name="salary"> 
    10             <return-column name="VALUE"/>
    11             <return-column name="CURRENCY"/>            
    12         </return-property>
    13     </return>
    14     { ? = call selectAllEmployments() }
    15 </sql-query>

    注意存儲過程當前僅僅返回標量和實體.現(xiàn)在不支持<return-join><load-collection>

    2.2.1. 使用存儲過程的規(guī)則和限制

    為了在Hibernate中使用存儲過程,你必須遵循一些規(guī)則.不遵循這些規(guī)則的存儲過程將不可用.如果你仍然想要使用他們, 你必須通過session.connection()來執(zhí)行他們.這些規(guī)則針對于不同的數(shù)據(jù)庫.因為數(shù)據(jù)庫 提供商有各種不同的存儲過程語法和語義.

    對存儲過程進行的查詢無法使用setFirstResult()/setMaxResults()進行分頁。

    建議采用的調用方式是標準SQL92: { ? = call functionName(<parameters>) } 或者 { ? = call procedureName(<parameters>}.原生調用語法不被支持。

    posted on 2008-04-22 12:34 鉤子 閱讀(1637) 評論(0)  編輯  收藏 所屬分類: opensources
    主站蜘蛛池模板: 在线观看亚洲免费视频| 亚洲国产成人九九综合| 亚洲av无码成人精品区一本二本| 最近中文字幕电影大全免费版| 亚洲综合色成在线播放| 一级毛片不卡免费看老司机| 亚洲国产天堂久久综合| eeuss影院www天堂免费| 在线a亚洲v天堂网2019无码| 最近更新免费中文字幕大全| 亚洲午夜久久久影院| 两个人看的www视频免费完整版| 亚洲一区二区女搞男| 永久免费AV无码网站国产| 久久久久亚洲精品日久生情 | jizz免费观看视频| 亚洲精品无码激情AV| 国产亚洲精品免费视频播放| 亚洲国产精品一区| 成人免费毛片内射美女APP| 亚洲日韩中文字幕一区| 又黄又爽无遮挡免费视频| 亚洲阿v天堂在线2017免费| 亚洲第一AV网站| 国产精品色拉拉免费看| 亚洲AV无码成人精品区日韩| 亚洲精品一级无码中文字幕| 另类免费视频一区二区在线观看| 亚洲精品午夜久久久伊人| 免费看的一级毛片| 成在人线av无码免费高潮水| 亚洲精品成人久久| 国产成人免费a在线视频色戒| eeuss影院免费92242部| 亚洲伊人久久精品| 免费一级毛片一级毛片aa| 久久午夜无码免费| 亚洲av无码有乱码在线观看| 久久亚洲精品视频| 国产精品无码素人福利免费| 成全在线观看免费观看大全|