[Hibernate]Hibernate 3.2: Transformers for HQL and SQL

          Posted on 2008-07-10 17:39 追夢人 閱讀(935) 評論(0)  編輯  收藏 所屬分類: Hibernate
          People using the Criteria API have either transparently or knowingly used a ResultTransformer. A ResultTransformer is a nice and simple interface that allows you to transform any Criteria result element. E.g. you can make any Criteria result be returned as a java.util.Map or as a non-entity Bean.

          Criteria TransformersImagine you have a StudentDTO class:
          public class StudentDTO
          {  
             private String studentName;  
             private String courseDescription;  
             public StudentDTO() {  }        
             ...
          }
          Then you can make the Criteria return non-entity classes instead of scalars or entities by applying a ResultTransformer:

          List resultWithAliasedBean = s.createCriteria(Enrolment.class)
               .createAlias("student", "st").createAlias("course", "co")
               .setProjection( Projections.projectionList()              
                                    .add( Projections.property("st.name"), "studentName" )                  
                                    .add( Projections.property("co.description"), "courseDescription" )          )          
               .setResultTransformer( Transformers.aliasToBean(StudentDTO.class) )        
                .list();
          StudentDTO dto = (StudentDTO)resultWithAliasedBean.get(0);  

          This is how ResultTransformer have been available since we introduced projection to the Criteria API in Hibernate 3.
          It is just one example of the built in transformers and users can provide their own transformers if they so please.
          Jealous programming Since I am more a HQL/SQL guy I have been jealous on Criteria for having this feature and I have seen many requests for adding it to all our query facilities.
          Today I put an end to this jealousy and introduced ResultTransformer for HQL and SQL in Hibernate 3.2.
          HQL TransformersIn HQL we already had a "kind" of result transformers via the ("select new" http://www.hibernate.org/hib_docs/v3/reference/en/html/queryhql.html#queryhql-select) syntax, but for returning non-entity beans it only provided value injection of these beans via its constructor. Thus if you used the same DTO in many different scenarios you could end up having many constructors on this DTO purely for allowing the "select new" functionality to work.
          Now you can get the value injected via property methods or fields instead, removing the need for explicit constructors.

          List resultWithAliasedBean = s.createQuery(  "select e.student.name as studentName," +  "       e.course.description as courseDescription" +  "from   Enrolment as e")
                 .setResultTransformer( Transformers.aliasToBean(StudentDTO.class))  .list();

          StudentDTO dto = (StudentDTO) resultWithAliasedBean.get(0);

            
          SQL TransformersWith native sql returning non-entity beans or Map's is often more useful instead of basic Object[]. With result transformers that is now possible.

          List resultWithAliasedBean = s.createSQLQuery(  "SELECT st.name as studentName, co.description as courseDescription " +  "FROM Enrolment e " +  "INNER JOIN Student st on e.studentId=st.studentId " +  "INNER JOIN Course co on e.courseCode=co.courseCode")
               .addScalar("studentName")  .addScalar("courseDescription")
               .setResultTransformer( Transformers.aliasToBean(StudentDTO.class))
              .list();

          StudentDTO dto =(StudentDTO) resultWithAliasedBean.get(0);

            
          Tip: the addScalar() calls were required on HSQLDB to make it match a property name since it returns column names in all uppercase (e.g. "STUDENTNAME"). This could also be solved with a custom transformer that search the property names instead of using exact match - maybe we should provide a fuzzyAliasToBean() method ;)
          Map vs. Object[]Since you can also use a transformer that return a Map from alias to value/entity (e.g. Transformers.ALIAS_TO_MAP), you are no longer required to mess with index based Object arrays when working with a result.

          List iter = s.createQuery(  "select e.student.name as studentName," +  "       e.course.description as courseDescription" +  "from   Enrolment as e")
               .setResultTransformer( Transformers.ALIAS_TO_MAP )  
               .iterate();

          String name = (Map)(iter.next()).get("studentName");

            
          Again, this works equally well for Criteria, HQL and native SQL.
           

          使用SQLQuery
          對原生SQL查詢執行的控制是通過SQLQuery接口進行的,通過執行Session.createSQLQuery()獲取這個接口。最簡單的情況下,我們可以采用以下形式:

          List cats = sess.createSQLQuery( " select * from cats " ).addEntity(Cat. class ).list();

          這個查詢指定了:

          SQL查詢字符串

          查詢返回的實體

          這里,結果集字段名被假設為與映射文件中指明的字段名相同。對于連接了多個表的查詢,這就可能造成問題,因為可能在多個表中出現同樣名字的字段。下面的方法就可以避免字段名重復的問題:

          List cats = sess.createSQLQuery( " select {cat.*} from cats cat " ).addEntity( " cat " , Cat. class ).list();

          這個查詢指定了:

          SQL查詢語句,它帶一個占位符,可以讓Hibernate使用字段的別名.

          查詢返回的實體,和它的SQL表的別名.

          addEntity()方法將SQL表的別名和實體類聯系起來,并且確定查詢結果集的形態。

          addJoin()方法可以被用于載入其他的實體和集合的關聯.

          List cats = sess.createSQLQuery(
          " select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id " )
          .addEntity(
          " cat " , Cat. class )
          .addJoin(
          " kitten " , " cat.kittens " )
          .list();

          原生的SQL查詢可能返回一個簡單的標量值或者一個標量和實體的結合體。

          Double max = (Double) sess.createSQLQuery( " select max(cat.weight) as maxWeight from cats cat " )
          .addScalar(
          " maxWeight " , Hibernate.DOUBLE);
          .uniqueResult();

          除此之外,你還可以在你的hbm文件中描述結果集映射信息,在查詢中使用。

          List cats = sess.createSQLQuery(
          " select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id " )
          .setResultSetMapping(
          " catAndKitten " )
          .list();

          命名SQL查詢
          可以在映射文檔中定義查詢的名字,然后就可以象調用一個命名的HQL查詢一樣直接調用命名SQL查詢.在這種情況下,我們不 需要調用addEntity()方法.

          < sql - query name = " persons " >
          < return alias = " person " class = " eg.Person " />
          Select person.NAME AS {person.name},person.AGE AS {person.age},person.SEX AS {person.sex} FROM PERSON person Where person.NAME LIKE :namePattern
          </ sql - query >
          List people = sess.getNamedQuery( " persons " ).setString( " namePattern " , namePattern)
          .setMaxResults(
          50 )
          .list();
          主站蜘蛛池模板: 开原市| 勐海县| 固始县| 阜城县| 绥中县| 鄂温| 五家渠市| 中西区| 雷山县| 绥芬河市| 兰州市| 肇源县| 板桥市| 新丰县| 桂林市| 宕昌县| 军事| 南平市| 凤凰县| 平远县| 淮滨县| 曲沃县| 贵州省| 普宁市| 陆丰市| 常州市| 阜新| 潢川县| 乌拉特后旗| 广水市| 黄浦区| 凤翔县| 云安县| 肥东县| 怀安县| 武汉市| 阿克| 新巴尔虎右旗| 浦城县| 石狮市| 治多县|