細心!用心!耐心!

          吾非文人,乃市井一俗人也,讀百卷書,跨江河千里,故申城一游; 一兩滴辛酸,三四年學業(yè),五六點粗墨,七八筆買賣,九十道人情。

          BlogJava 聯(lián)系 聚合 管理
            1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks
          JPA本地查詢(Native Query)(一)
          2010-01-20 10:49

          JPA支持本地查詢,所謂本地查詢,就是使用原生的sql語句(根據(jù)數(shù)據(jù)庫的不同,在sql的語法或結(jié)構(gòu)方面可能有所區(qū)別)進行查詢數(shù)據(jù)庫的操作。

           

          本地查詢主要使用EntityManager接口里的方法:

          public interface EntityManager {
          public void persist(Object entity);
          public <T> T find(Class <T> entityClass, Object primaryKey);
          public <T> T getReference(Class <T> entityClass, Object primaryKey);
          public <T> T merge(T entity);
          public void remove(Object entity);
          public void lock(Object entity, LockModeType lockMode);

          public void refresh(Object entity);
          public boolean contains(Object entity);
          public void clear( );

          public void joinTransaction( );
          public void flush( );
          public FlushModeType getFlushMode( );
          public void setFlushMode(FlushModeType type);

          public Query createQuery(String queryString);
          public Query createNamedQuery(String name);

            
          public Query createNativeQuery(String sqlString);
          public Query createNativeQuery(String sqlString, String resultSetMapping);
          public Query createNativeQuery(String sqlString, Class resultClass);


             public Object getDelegate( );

          public void close( );
          public boolean isOpen( );
          }

           

          createNativeQuery方法的三種形式,但用這個方法的缺點是,要將查詢的sql語句及返回結(jié)果集類型傳遞進去。還有一種方法是使用createNamedQuery,這樣就可以避免在這里直接寫入sql語句以及返回的結(jié)果集類型等參數(shù),而可以在相關(guān)的Entity類里對這些信息進行配置。

           

          //這里只是傳遞進去一個string

          Query q = em.createNamedQuery("ReturnOrderListWithFullScalarType");

          //這里是設定在sql中所需的參數(shù)

          q.setParameter(1, customer.getId());

          //得到結(jié)果集

          List orderList = q.getResultList();

           

           

          這個查詢主要是根據(jù)用戶的id 來獲取他名下的所有訂單。所以,在實體類 Order中,加入相關(guān)的native query annotation.

           

          @NamedNativeQueries

          (

              {

                 @NamedNativeQuery(

                     name="ReturnOrderListWithFullScalarType",

                        query="select o.id as order_id,o.create_date as order_creation_date,o.description as order_description,o.sum_price as order_sum_total,

          c.name as customer_name,c.ctype as customer_type,c.id as customer_id from orders o join customer c on o.cust_id=c.id where o.cust_id=?1",

                     resultSetMapping="ReturnOrderListWithFullScalarType"),

                  。。。。。。。。。。。。。可能還有更多的本地查詢設置

          }

          )

           

          @NamedNativeQueries 如果在一個實體類中有多個NamedNativeQuery的話,必須使用該批注,并且將單個的NamedNativeQuery都作為NamedNativeQueries數(shù)組中的一個元素。

          @NamedNativeQuery,在這里設置關(guān)于該本地查詢的信息。name表示傳遞進EntityManager.createNamedQuery(“name”)的參數(shù),query表示實施本地查詢的sql語句,resultSetMapping表示返回結(jié)果集的映射方式。它的意思就是結(jié)果集將以哪種形式來保存。

           

          接著,就要設置這個結(jié)果集的映射方式了。

           

          @SqlResultSetMappings(

          {

              @SqlResultSetMapping

              (

                 name="ReturnOrderListWithFullScalarType",

                 entities={},

                 columns=

                 {

                     @ColumnResult(name="order_id"),

                     @ColumnResult(name="order_creation_date"),

                     @ColumnResult(name="order_description"),

                     @ColumnResult(name="order_sum_total"),

                     @ColumnResult(name="customer_id"),

                     @ColumnResult(name="customer_name")

                 }

              ),

                 。。。。。。。。。。。。。可能還有更多的結(jié)果集映射設置

          })

          針對每一個本地查詢的返回值,都有一個結(jié)果集和它映射。它可以返回

          1. 實體(包括不同類型的實體,即多個實體) Entity

          2. 標量值 Scalar

          3. 實體與標量值的組合 Entity+Scalar

           

          默認情況下,JPA假設原生sql查詢中select語句將會:

          1.      返回一個實體類型

          2.      包含與返回的實體的所有字段或?qū)傩韵鄬乃辛校戳忻蛯嶓w屬性/字段名一樣

          3.      查詢中沒有用列名別名,column alias,即沒有用 AS 指定別名

           

          @SqlResultSetMappings,如果在一個實體類中有多個@NamedNativeQuery的話,必然就有多個結(jié)果集映射@SqlResultSetMapping。在這種情況下,必須使用該批注,并且將單個的SqlResultSetMapping都作為SqlResultSetMappings數(shù)組中的一個元素。

          @SqlResultSetMapping,關(guān)于結(jié)果集映射的詳細信息。

          name 表示該結(jié)果集映射的名字,與@NamedNativeQuery中的resultSetMapping="ReturnOrderListWithFullScalarType"的值相對應。

          entities表示查詢結(jié)果集會被映射進實體,如果有就要將所有返回的實體一一列出(這里我們將結(jié)果集全部映射進標量,所以entities屬性是個空數(shù)組)。

          columns表示將被映射進標量的結(jié)果集中的各個列。

           

          這里要說一下標量(Scalar)這個概念。在物理學上,標量與矢量(Vector)是相互對應的,矢量是既有方向又有大小的量,而標量是只有大小的量。在此處,Scalar的含義與物理學上的定義差不多,Scalar可以認為是一個沒有屬性/方法的單純的常量(可以想象為java數(shù)據(jù)類型的primitive type),而與它相對的則是有方法/屬性的對象(object type)。那么采用這種映射機制,我們從數(shù)據(jù)庫取來的每一條記錄的每一個字段,僅僅是被單純的作為一個常量,保存在每一個columnResult中。

           

          @ ColumnResult,就是指在sql語句中,將哪些查詢的列保存進來。每一個@ColumnResult對應一個列,name="order_id" ,注意,如果在select的時候,用AS 制定了列的別名,“order_id” 則表示的是別名。

           

          這種映射方式比較簡單,我們可以推測,得到的結(jié)果集List中,數(shù)據(jù)會是這樣:

          [ {“1”, “2”, “3”, …},  {“1”, “2”, “3”, …}, …… ]

           

          經(jīng)過運行測試程序,得到了我們的推論

           

           

          *****ReturnOrderListWithFullScalarType*****

          52 2009-05-27 00:00:00.0    This is an order creation example. 36817.0    39 John Smith

          55 2009-05-27 00:00:00.0    This is an order creation example. 3347.0 39 John Smith

          ……

           

          將結(jié)果集全部映射進標量,是比較簡單的一種做法,在SqlResultSetMapping

          posted on 2012-06-15 21:38 張金鵬 閱讀(8525) 評論(0)  編輯  收藏 所屬分類: JPA
          主站蜘蛛池模板: 台北县| 定南县| 新竹县| 金堂县| 岚皋县| 洪江市| 清新县| 喀什市| 固镇县| 博罗县| 南充市| 正宁县| 潜山县| 岳西县| 阜宁县| 和田市| 永靖县| 木里| 临夏市| 云林县| 美姑县| 清远市| 大田县| 阿荣旗| 台南县| 鹿邑县| 宝清县| 泸水县| 上高县| 蛟河市| 桂林市| 依安县| 民丰县| 宜兰市| 辽阳县| 滨州市| 丰台区| 瓦房店市| 太保市| 秦皇岛市| 常宁市|