OK,現(xiàn)在對同一個查詢,再把結(jié)果集全部映射進(jìn)實體對象。
首先 @NamedNativeQueries ( { @NamedNativeQuery( name="ReturnOrderListWithFullEntityType", 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="ReturnOrderListWithFullEntityType"), 。。。。。。。。。。。。。可能還有更多的本地查詢設(shè)置 } ) 改變本地查詢的resultSetMapping
@SqlResultSetMapping ( name="ReturnOrderListWithFullEntityType", entities= { @EntityResult ( entityClass=entity.Order.class, fields= { @FieldResult(name="id",column="order_id"), @FieldResult(name="date",column="order_creation_date"), @FieldResult(name="desc",column="order_description"), @FieldResult(name="sum",column="order_sum_total") } ),
@EntityResult ( entityClass=entity.Customer.class, discriminatorColumn="customer_type", fields= { @FieldResult(name="id",column="customer_id"), @FieldResult(name="name",column="customer_name") } ) }, columns={} )
entities屬性是一個包含與返回結(jié)果集相映射的所有實體的一個數(shù)組。這條查詢得到了訂單和用戶的信息,所以,與結(jié)果集映射的實體,就應(yīng)該是Order和Customer。 每一個映射實體用@EntityResult表示,entityClass表示實體類,fields表示該實體類中的屬性,與查詢結(jié)果中的哪些個列相映射。而每一個“屬性<->列”的映射關(guān)系,又保存在@FieldResult里面。name是實體屬性,column是查詢列(或列別名)
要注意的是,如果要將結(jié)果集映射到實體對象,則 1.Select 語句中必須包含實體所映射的表中的PK,也就是 select o.id as order_id
2. 反過來,“屬性<->列”的映射,也必須將表的PK映射到實體類的用@Id annotation批注的字段或?qū)傩陨稀?/span>
否則,JPA就會拋出一個exception oracle.toplink.essentials.exceptions.QueryException Exception Description: The primary key read from the row [DatabaseRecord( orders.ID => null orders.CREATE_DATE => 2009-05-27 00:00:00.0 orders.SUM_PRICE => 36817.0 orders.DESCRIPTION => This is an order creation example. orders.cust_id => null)] during the execution of the query was detected to be null. Primary keys must not contain null.
再看一下關(guān)于Customer實體的映射,與Order不一樣的地方,是discriminatorColumn="customer_type" (可能為列別名) 加上這個屬性的原因是,Customer類是一個父類,以供其他子類繼承,而J PA的內(nèi)在多態(tài)性機(jī)制將會獲取到Customer的實際類型。根據(jù)J PA @Inheritance批注,得知,父類實體的表中必須有一個字段(默認(rèn)為DTYPE)來表示各個子類的類型。所以當(dāng)要將查詢結(jié)果集保存為實體的時候,它必須要知道你所保存的這個Customer實體到底是哪種類型。 所以,你還必須在select子句中取得這個Discrimator Type的字段。 否則又會拋出異常: oracle.toplink.essentials.exceptions.QueryException Exception Description: Custom SQL failed to provide descriminator column : , as defined in SQLResultSetMapping : ReturnOrderListWithFullEntityType. 或者: oracle.toplink.essentials.exceptions.QueryException Exception Description: Custom SQL failed to provide descriminator column : customer_type, as defined in SQLResultSetMapping : ReturnOrderListWithPartEntityPartScalarType.
通過這種映射方式,我們可以推測,得到的結(jié)果集List中,數(shù)據(jù)會是這樣: [ {“Order對象1”, “Customer對象1”}, {“Order對象2”, “Customerr對象2”}, …… ]
經(jīng)過運行測試程序,得到了我們的推論
*****ReturnOrderListWithFullEntityType***** entity.Order@48edb5 entity.GoldenCustomer@1ee2c2c entity.Order@1402d5a entity.GoldenCustomer@1ee2c2c entity.Order@1e13e07 entity.GoldenCustomer@1ee2c2c entity.Order@9cfec1 entity.GoldenCustomer@1ee2c2c entity.Order@747fa2 entity.GoldenCustomer@1ee2c2c …… 看來的確是保存了對象,而且注意第二個對象不是Customer而是GoldenCustomer,這說明,JPA自動將數(shù)據(jù)映射進(jìn)了GoldenCustomer實體(盡管我們使用的是Customer實體進(jìn)行保存 “entityClass=entity.Customer.class”) |
JPA本地查詢(Native Query)(二)
2010-01-20 10:49