1. 程式人生 > >關於hql中部分關聯欄位為空時,不報錯而直接查不出欄位為空的記錄

關於hql中部分關聯欄位為空時,不報錯而直接查不出欄位為空的記錄

 select b.listNo,b.appGNo,b.trGno,b.complex,b.commName,b.commSpec,b.tradeUnit,b.tradeQty,b.unit,b.qty,b.note,
                 c.listNo,c.appGNo,c.trGno,c.complex,c.commName,c.commSpec,c.tradeUnit,c.tradeQty,c.unit,c.qty,c.note,
                 a.companyCode,a.companyName,a.billNo, 
                 a.seqNo,a.appNo,a.declareState ,a.messageIndentureType 
                 from  MessageIndentureHead a , KHMessageIndenture b , GYSMessageIndenture c  where a.id = c.messageIndentureHead.id and a.id = b.messageIndentureHead.id 
                 and ((a.messageIndentureType = 1 and b.listNo = c.outNo) 
                 or (a.messageIndentureType = 0 and c.listNo = b.outNo))

如上hql程式碼,查詢,會出現先TradeUnit為欄位空的記錄將不會被查詢出來。(MessageIndentureHead擁有對tradeunit的unit表的單向一對多關聯)

注意到hibernate根據hql輸出的sql如下:

select khmessagei1_.listNo as col_0_0_, khmessagei1_.appGNo as col_1_0_, khmessagei1_.trGno as col_2_0_,
 khmessagei1_.complex as col_3_0_, khmessagei1_.commName as col_4_0_, khmessagei1_.commSpec as col_5_0_, 
khmessagei1_.tradeUnit_code as col_6_0_, khmessagei1_.tradeQty as col_7_0_, khmessagei1_.unit_code as col_8_0_,
 khmessagei1_.qty as col_9_0_, khmessagei1_.note as col_10_0_, gysmessage2_.listNo as col_11_0_, gysmessage2_.appGNo as col_12_0_,
 gysmessage2_.trGno as col_13_0_, gysmessage2_.complex as col_14_0_, gysmessage2_.commName as col_15_0_, 
gysmessage2_.commSpec as col_16_0_, gysmessage2_.tradeUnit_code as col_17_0_, gysmessage2_.tradeQty as col_18_0_,
 gysmessage2_.unit_code as col_19_0_, gysmessage2_.qty as col_20_0_, gysmessage2_.note as col_21_0_,
 messageind0_.companyCode as col_22_0_, messageind0_.companyName as col_23_0_, messageind0_.billNo as col_24_0_,
 messageind0_.seqNo as col_25_0_, messageind0_.appNo as col_26_0_, messageind0_.declareState as col_27_0_,
 messageind0_.messageIndentureType as col_28_0_, unit3_.code as code90_0_, unit4_.code as code90_1_, unit5_.code as code90_2_,
 unit6_.code as code90_3_, unit3_.isOut as isOut90_0_, unit3_.modifyDate as modifyDate90_0_, unit3_.modifyUser as modifyUser90_0_,
 unit3_.name as name90_0_, unit4_.isOut as isOut90_1_, unit4_.modifyDate as modifyDate90_1_, unit4_.modifyUser as modifyUser90_1_, 
unit4_.name as name90_1_, unit5_.isOut as isOut90_2_, unit5_.modifyDate as modifyDate90_2_, unit5_.modifyUser as modifyUser90_2_, 
unit5_.name as name90_2_, unit6_.isOut as isOut90_3_, unit6_.modifyDate as modifyDate90_3_, unit6_.modifyUser as modifyUser90_3_,
 unit6_.name as name90_3_ 
from MessageIndentureHead messageind0_ cross join KHMessageIndenture khmessagei1_ inner join Unit unit3_ on khmessagei1_.tradeUnit_code=unit3_.code
 inner join Unit unit4_ on khmessagei1_.unit_code=unit4_.code cross join GYSMessageIndenture gysmessage2_ inner join Unit unit5_ on gysmessage2_.tradeUnit_code=unit5_.code inner join Unit unit6_ on gysmessage2_.unit_code=unit6_.code where messageind0_.id=gysmessage2_.messageIndentureHead_id and messageind0_.id=khmessagei1_.messageIndentureHead_id and  (messageind0_.messageIndentureType=1 and khmessagei1_.listNo=gysmessage2_.outNo or messageind0_.messageIndentureType=0 and  gysmessage2_.listNo=khmessagei1_.outNo)

注意到hibernate輸出的sql是對unit表使用內連線的,這就解釋了為何該欄位為空的記錄不會輸出。

原因:

使用a.xx,去查出a關聯的表中的資料會導致隱式是用內連線(原因據說是與‘n+1’問題有關)

網上找的資料:

對於Hibernate3.2.3以後的版本,如果關聯實體是單個實體或單個的元件屬性,HQL依然可以似乎用英文點號(.)來隱式連線關聯實體或元件;但如果關聯實體是集合(包括1-N關聯、N-N關聯和集合元素時元件等),則必須使用xxx join來顯示連線關聯實體或元件。

解決辦法:

顯示宣告為外連線連線該些欄位

 select b.listNo,b.appGNo,b.trGno,b.complex,b.commName,b.commSpec,uc,b.tradeQty,ud,b.qty,b.note,
 c.listNo,c.appGNo,c.trGno,c.complex,c.commName,c.commSpec,ua,c.tradeQty,ub,null,c.qty,c.note,
 a.companyCode,a.companyName,a.billNo, 
 a.seqNo,a.appNo,a.declareState ,a.messageIndentureType 
 from  MessageIndentureHead a , KHMessageIndenture b , GYSMessageIndenture c
left join c.tradeUnit ua left join c.unit ub left join b.tradeUnit uc left join b.unit ud
  where a.id = c.messageIndentureHead.id and a.id = b.messageIndentureHead.id