日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Hibernate框架中直接操作JDBC接口實(shí)例

Hibernate是一個(gè)開(kāi)放源代碼的對(duì)象關(guān)系映射框架,它對(duì)JDBC進(jìn)行了非常輕量級(jí)的對(duì)象封裝,使得Java程序員可以隨心所欲的使用面向?qū)ο缶幊趟季S來(lái)操縱數(shù)據(jù)庫(kù)。

成都創(chuàng)新互聯(lián)公司專(zhuān)注為客戶(hù)提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、坡頭網(wǎng)絡(luò)推廣、成都微信小程序、坡頭網(wǎng)絡(luò)營(yíng)銷(xiāo)、坡頭企業(yè)策劃、坡頭品牌公關(guān)、搜索引擎seo、人物專(zhuān)訪(fǎng)、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供坡頭建站搭建服務(wù),24小時(shí)服務(wù)熱線(xiàn):028-86922220,官方網(wǎng)址:www.cdcxhl.com

Hibernate的優(yōu)勢(shì)在于屏蔽了數(shù)據(jù)庫(kù)細(xì)節(jié),對(duì)于新增修改刪除的數(shù)據(jù)層操作,不再需要跟具體的SQL語(yǔ)句打交道,簡(jiǎn)單的對(duì)對(duì)象實(shí)例進(jìn)行增刪改操作即可。但是,對(duì)于多表關(guān)聯(lián)、分組統(tǒng)計(jì)、排序等復(fù)雜的查詢(xún)功能時(shí),由于Hibernate自身的O-R映射機(jī)制,父子表之間關(guān)聯(lián)取數(shù)據(jù)會(huì)產(chǎn)生大量冗余的查詢(xún)操作,性能低下。此類(lèi)情況下,直接使用JDBC的SQL語(yǔ)句反而更加靈活和高效。

Hibernate框架處理復(fù)雜查詢(xún)問(wèn)題實(shí)例分析

考慮如下數(shù)據(jù)庫(kù)實(shí)體示例,表A為主表,表B和表C為子表,A與B、A與C表均為1對(duì)多關(guān)系,在B表和C表中以A_ID外鍵字段關(guān)聯(lián)A表父記錄。

 
圖 1.數(shù)據(jù)庫(kù)實(shí)體示例圖

在Hibernate框架中,通常采用以下配置方式完成A表與B,C表父子實(shí)體之間的級(jí)聯(lián)查詢(xún)操作,Hibernate實(shí)體配置xml如下:

 
 
 
 
  1. 清單1.hibernate實(shí)體配置xml  
  2. A.hbm.xml:  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21. B.hbm.xml:  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36. C.hbm.xml  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  

對(duì)應(yīng)的Hibernate領(lǐng)域?qū)嶓w類(lèi)代碼示例如下:

 
 
 
 
  1. 清單2.hibernate實(shí)體類(lèi)示例  
  2. A.java:  
  3. publicclassAimplementsjava.io.Serializable,Comparable{  
  4. privatelongid;  
  5. privateSetchildren_b=newHashSet();  
  6. privateSetchildren_c=newHashSet();  
  7.  
  8. publicA(longid){  
  9. this.id=id;  
  10. }  
  11.  
  12. publiclonggetId(){  
  13. returnid;  
  14. }  
  15.  
  16. publicvoidsetId(longid){  
  17. this.id=id;  
  18. }  
  19.  
  20. publicSetgetChildern_b(){  
  21. returnchildren_b;  
  22. }  
  23.  
  24. publicvoidsetChildren_b(Setchildren_b){  
  25. this.children_b=children_b;  
  26. }  
  27.  
  28. publicSetgetChildern_c(){  
  29. returnchildren_c;  
  30. }  
  31.  
  32. publicvoidsetChildren_c(Setchildren_c){  
  33. this.children_c=children_c;  
  34. }  
  35.  
  36. publicintcompareTo(Objectother){  
  37. AotherSubject=(A)other;  
  38. longcurAmount=this.getChildren_b().size()+this.getChildren_c().size();  
  39. longotherAmount=otherSubject.getChildren_b().size()  
  40.  +otherSubject.getChildren_c().size();  
  41. if(curAmount
  42. {  
  43. return-1;  
  44. }  
  45. elseif(curAmount>otherAmount)  
  46. {  
  47. return1;  
  48. }  
  49. else  
  50. {  
  51. return0;  
  52. }  
  53. }  
  54. }  
  55.  
  56. B.java:  
  57. publicclassBimplementsjava.io.Serializable,Comparable{  
  58. privatelongid;  
  59. privatelonga_id;  
  60.  
  61. publiclonggetId(){  
  62. returnid;  
  63. }  
  64.  
  65. publicvoidsetId(longid){  
  66. this.id=id;  
  67. }  
  68.  
  69. publiclonggetA_id(){  
  70. returna_id;  
  71. }  
  72.  
  73. publicvoidsetA_id(longa_id){  
  74. this.a_id=a_id;  
  75. }  
  76.  
  77. publicB(longid){  
  78. this.id=id;  
  79. }  
  80. }  
  81.  
  82. C.java:  
  83. publicclassCimplementsjava.io.Serializable,Comparable{  
  84. privatelongid;  
  85. privatelonga_id;  
  86.  
  87. publiclonggetId(){  
  88. returnid;  
  89. }  
  90.  
  91. publicvoidsetId(longid){  
  92. this.id=id;  
  93. }  
  94.  
  95. publiclonggetA_id(){  
  96. returna_id;  
  97. }  
  98.  
  99. publicvoidsetA_id(longa_id){  
  100. this.a_id=a_id;  
  101. }  
  102.  
  103. publicC(longid){  
  104. this.id=id;  
  105. }  

假設(shè)現(xiàn)在要統(tǒng)計(jì)A表中從屬的B表和C表記錄之和最高的top10的A表記錄,在Hibernate框架下,由于取A表對(duì)應(yīng)的數(shù)據(jù)庫(kù)記錄時(shí),已關(guān)聯(lián)取出了對(duì)應(yīng)的B、C表子記錄存放于A實(shí)體類(lèi)的children_a,children_c的屬性中,因此top10的功能可以通過(guò)比較每個(gè)A表實(shí)體類(lèi)中children_a、children_c的Set的size大小并進(jìn)行排序得到,其代碼示例如下:

 
 
 
 
  1. 清單3.排序代碼示例  
  2. privateArrayListsortAByAmount(ArrayListall)  
  3. {  
  4. for(inti=0;i
  5. {  
  6. for(intj=0;j
  7. {  
  8. if(all.get(j).compareTo(all.get(j+1))<=0)  
  9. {  
  10. Atemp=all.get(j);  
  11. all.set(j,all.get(j+1));  
  12. all.set(j+1,temp);  
  13. }  
  14. }  
  15. }  
  16. returnall;  

表面看來(lái)很方便,但是由于Hibernate是面向?qū)ο蟮腛-R映射機(jī)制,每一條A表記錄的查詢(xún)實(shí)際都關(guān)聯(lián)有兩條B、C表查詢(xún)的SQL產(chǎn)生,我們可以看到Hibernate的SQL日志中:

 
 
 
 
  1. 清單4.Hibernatesql日志示例  
  2. Hibernate:selecta0_.IDasID2_fromAa0_wherea0_.ID='1' 
  3. Hibernate:selectb0_.IDasID2_,b0_.A_IDasA_ID2_fromBb0_whereb0_.ID=?  
  4. Hibernate:selectc0_.IDasID2_,c0_.A_IDasA_ID2_fromCc0_wherec0_.ID=? 

由上述Sql日志可以看出,每一條A表記錄的取出,都伴隨以A表ID為查詢(xún)條件關(guān)聯(lián)B,C表中A_ID外鍵字段的2條取子記錄的sql,這是由A.hbm.xml配置中“l(fā)azy=false”決定的。#p#

這種情況下,當(dāng)A和B、C表中數(shù)據(jù)量越來(lái)越大時(shí),A表取實(shí)體的操作開(kāi)銷(xiāo)將隨著sql查詢(xún)的增多而增大,并且在緊接著的排序過(guò)程中,即使采用業(yè)界最快的快速排序算法,排序時(shí)間依然是隨原始排序?qū)嶓w數(shù)量的線(xiàn)性關(guān)系(O(nlgn)),效率會(huì)線(xiàn)性下降,最終無(wú)法滿(mǎn)足客戶(hù)的前臺(tái)查詢(xún)的效率要求。此類(lèi)情況下如直接采用JDBC,則只需一條如下的SQL語(yǔ)句,即可完成該功能:

 
 
 
 
  1. 清單5.直接JDBC操作sql  
  2. select  
  3. tab1.ID,  
  4. tab1.sumCol+tab2.sumCol  
  5. from  
  6. (  
  7. selecta.ID,  
  8. count(b.ID)sumCol  
  9. fromAaleftjoinBbona.ID=b.ID  
  10. GROUPBY  
  11. a.ID  
  12. )tab1,  
  13. (  
  14. selecta.ID,  
  15. count(c.ID)sumCol  
  16. fromAaleftjoinCcona.ID=c.ID  
  17. GROUPBY  
  18. a.ID  
  19. )tab2  
  20. wheretab1.ID=tab2.ID  
  21. orderbytab1.sumCol+tab2.sumColdesc 

在以上JDBC方式下,即使A、B、C表的數(shù)據(jù)量持續(xù)增長(zhǎng),仍然只有1條SQL的開(kāi)銷(xiāo),不會(huì)出現(xiàn)SQL遞增的情況,因此耗時(shí)是在可控制的區(qū)間內(nèi)的。并且讀者可以注意到上述SQL將3表關(guān)聯(lián)拆分成了2個(gè)子查詢(xún),這樣避免了3表做笛卡爾積的數(shù)量和,進(jìn)一步提高了查詢(xún)效率。由此可見(jiàn),直接操作JDBC,除SQL的開(kāi)銷(xiāo)可控外,還可以利用數(shù)據(jù)庫(kù)層各種機(jī)制,如上述查詢(xún)語(yǔ)句中的leftjoin、子查詢(xún)、索引…,靈活的調(diào)整SQL語(yǔ)句,以達(dá)到最佳的查詢(xún)性能。

由上可實(shí)例可看出,在多表關(guān)聯(lián)、排序等復(fù)雜的查詢(xún)情況下,Hibernate框架由于其自身對(duì)象封裝的特殊性,不能像JDBC直接操作SQL那樣很好的解決查詢(xún)中高效性和靈活性方面的需求,且由于其屏蔽了數(shù)據(jù)庫(kù)的底層,開(kāi)發(fā)人員看到的只是Hibernate提供的數(shù)據(jù)層API,無(wú)法與靈活的使用SQL語(yǔ)句等數(shù)據(jù)庫(kù)底層細(xì)節(jié)。因此,有必要在Hibernate框架中提供直接操作JDBC的接口。

在Hibernate框架中提供操作JDBC的接口的解決方案

Hibernate的session機(jī)制

我們知道Hibernate框架本身也是建立在JDBC之上的數(shù)據(jù)持久層實(shí)現(xiàn),因此,要在框架本身提供操作JDBC的接口,需要切入其對(duì)JDBC封裝的細(xì)節(jié)。通過(guò)研究和查閱Hibernate的框架源代碼及參考文檔,我們發(fā)現(xiàn),Hibernate的Session會(huì)話(huà)是進(jìn)行持久化的基礎(chǔ),所有的持久化操作都是在Session的基礎(chǔ)上進(jìn)行的,在實(shí)現(xiàn)上它是和JDBC中的connection數(shù)據(jù)庫(kù)連接綁定的,也就是說(shuō),Hibernate的會(huì)話(huà)域基于一個(gè)實(shí)際的connection類(lèi)實(shí)例,二者之間的關(guān)系如下圖所示:

 
圖 2.Hibernate Session機(jī)制示意圖

由上可以看到,Hibernate中的session是單線(xiàn)程的,代表了一次會(huì)話(huà)的過(guò)程。實(shí)際上是把一個(gè)JDBCConnection打包了,每一個(gè)Session實(shí)例和一個(gè)數(shù)據(jù)庫(kù)事務(wù)綁定。其生命周期是與與之關(guān)聯(lián)的connection實(shí)例的生命周期一致的。

具體解決方案

由上面的Hibernate的Session機(jī)制我們意識(shí)到,只要能獲取到Hibernate當(dāng)前會(huì)話(huà)中的Connection,則獲得了JDBC的底層數(shù)據(jù)庫(kù)連接實(shí)例,剩下就都是JDBC的范疇了。再查閱Hibernate的API,發(fā)現(xiàn)HibernateTemplate類(lèi)中SessionFactory成員的getCurrentSession()方法即可獲得Hibernate環(huán)境下的當(dāng)前活動(dòng)的Session會(huì)話(huà),而Hibernate中Session實(shí)例的connection()方法即可獲得該會(huì)話(huà)中綁定的Connection數(shù)據(jù)庫(kù)連接實(shí)例。

問(wèn)題迎刃而解了,既然可以操作Connection實(shí)例,那與之關(guān)聯(lián)的Statement、ResultSet等基本JDBC類(lèi)均在我們控制范圍中了,我們采用接口模式設(shè)計(jì)一個(gè)輕量級(jí)解決方案,使其在保持原Hibernate的增刪改操作方式前提下靈活提供操作JDBC的接口。設(shè)計(jì)類(lèi)圖如下圖所示:

 
圖 3.解決方案設(shè)計(jì)類(lèi)示意圖

設(shè)計(jì)中,AbstractHibernateDao類(lèi)作為DAO操作的基本類(lèi),保留原有Hibenrate框架下的新增,修改,刪除等API。BaseHibernateDao類(lèi)繼承AbstractHibernateDao類(lèi),在此類(lèi)中增加了直接操作JDBC的接口。設(shè)計(jì)getConnection方法獲取JDBC的數(shù)據(jù)庫(kù)連接實(shí)例,設(shè)計(jì)getObjectsBySql方法作為對(duì)外的主要接口,該方法調(diào)用fetchObjects方法,這是具體的數(shù)據(jù)庫(kù)記錄到領(lǐng)域?qū)ο蟮霓D(zhuǎn)換操作,需要使用者override該方法以完成自有領(lǐng)域?qū)ο蟮奶畛浼?xì)節(jié)。實(shí)際實(shí)現(xiàn)的類(lèi)代碼如下所示:

 
 
 
 
  1. 清單6.解決方案實(shí)現(xiàn)代碼  
  2. AbstractHibernateDao.java:  
  3. abstractpublicclassAbstractHibernateDaoextendsHibernateDaoSupport{  
  4.  
  5. protectedLoglogger=LogFactory.getLog(getClass());  
  6. protectedClassentityClass;  
  7.  
  8. protectedClassgetEntityClass(){  
  9. returnentityClass;  
  10. }  
  11.  
  12. publicListgetAll(){  
  13. returngetHibernateTemplate().loadAll(getEntityClass());  
  14. }  
  15.  
  16. publicvoidsave(Objecto){  
  17. getHibernateTemplate().saveOrUpdate(o);  
  18. }  
  19.  
  20. publicvoidremoveById(Serializableid){  
  21. remove(get(id));  
  22. }  
  23.  
  24. publicvoidremove(Objecto){  
  25. getHibernateTemplate().delete(o);  
  26. }  
  27.  
  28. }  
  29.  
  30. BaseHibernateDao.java:  
  31. abstractpublicclassBaseHibernateDaoextendsAbstractHibernateDao{  
  32. publicConnectiongetConnection()  
  33. {  
  34. try  
  35. {  
  36.  
  37. SessioncurSeesion=null;  
  38. Connectioncon=null;  
  39. curSeesion=super.getHibernateTemplate().getSessionFactory()  
  40.  .getCurrentSession();  
  41. con=curSeesion.connection();  
  42. returncon;  
  43. }  
  44. catch(Exceptiones)  
  45. {  
  46. System.out.println(es.getMessage());  
  47. returnnull;  
  48. }  
  49.  
  50. }  
  51.  
  52. publicArrayListfetchObjects(ResultSetrs)  
  53. {  
  54. ArrayListret=newArrayList();  
  55. //example:  
  56. //while(rs.next())  
  57. //{  
  58. //Objectobject=newObject();  
  59. //rs.getString(1);  
  60. //rs.getString(2);  
  61. //ret.add(object);      
  62. //}  
  63. returnret;  
  64. }  
  65.  
  66. publicArrayListgetObjectsBySql(StringpureSql)  
  67. {  
  68. Connectioncon=curSeesion.connection();  
  69. ps=con.prepareStatement(sqlbuf.toString());  
  70. rs=ps.executeQuery();  
  71. try  
  72. {  
  73. returnthis.fetchObjects(rs);   
  74.      
  75. }  
  76. catch(Exceptiones)  
  77. {  
  78. System.out.println(es.getMessage());  
  79. returnnull;  
  80. }  
  81. finally  
  82. {  
  83. try  
  84. {  
  85. ps.close();  
  86. rs.close();  
  87. con.close();  
  88. }  
  89. catch(SQLExceptione){  
  90. //TODOAuto-generatedcatchblock  
  91. e.printStackTrace();  
  92. }  
  93.      
  94. }  
  95. }  
  96. 使用該解決方案時(shí),只需要將代碼包解壓至項(xiàng)目源代碼目錄,在想要直接操作JDBC接口的DAO模塊繼承BaseHibernateDao類(lèi),然后重寫(xiě)fetchObjects方法填入從自身數(shù)據(jù)庫(kù)表字段填充到領(lǐng)域?qū)ο蟮牟僮?即可輕松調(diào)用getObjectsBySql傳入原生SQL語(yǔ)句,返回具體的領(lǐng)域?qū)ο髮?shí)體集合,當(dāng)然使用者也可以通過(guò)getConnection獲得JDBC的Connection實(shí)例來(lái)進(jìn)行自己需要的特定的JDBC底層操作。仍然以上文中的A、B、C表為例,采用該解決方案完成top10取數(shù)的代碼示例如下:

     
     
     
     
    1. 清單7.使用解決方案示例  
    2. publicclasstestDAOextendsBaseHibernateDao{  
    3.  
    4. privateStringsqlQuery="selecttab1.ID,tab1.sumCol+tab2.sumCol"+  
    5. "from(selecta.ID,count(b.ID)sumCol"+  
    6. "fromAaleftjoinBbona.ID=b.ID"+  
    7. "GROUPBYa.ID)tab1,"+  
    8. "(selecta.ID,count(c.ID)sumCol"+  
    9. "fromAaleftjoinCcona.ID=c.ID"+  
    10. "GROUPBYa.ID)tab2"+  
    11. "wheretab1.ID=tab2.ID"+  
    12. "orderbytab1.sumCol+tab2.sumColdesc";  
    13.  
    14. @override  
    15. publicArrayListfetchObjects(ResultSetrs)  
    16. {  
    17. ArrayListret=newArrayList();  
    18. intcount=1;  
    19. while(rs.next())  
    20. {  
    21. Aa=newA();  
    22. a.setId(rs.getLong(1));  
    23. System.out.println("top"+(count++)+"amount:"+rs.getLong(2));  
    24. ret.add(object);      
    25. }  
    26. returnret;  
    27. }  
    28.  

    解決方案驗(yàn)證

    在實(shí)際mySql數(shù)據(jù)庫(kù)環(huán)境中,以A表數(shù)據(jù)量1000條,B表數(shù)據(jù)量3W多條,C表數(shù)據(jù)量2000條情況下進(jìn)行上文中提到的top 10的操作,采用Hibernate的耗時(shí)和用JDBC接口解決方案的效率比較如下:

     
    表 1.Hibernate框架方式與JDBC接口方式效率比較

     
    表 2.Hibernate框架方式與JDBC接口方式效率比較

    由以上結(jié)果可以看出:在數(shù)據(jù)量遞增的情況下,采用Hibernate方式下效率與庫(kù)表數(shù)據(jù)呈線(xiàn)性增長(zhǎng),且排序的操作的效率也是一樣,而直接采用JDBC接口解決方案下效率遠(yuǎn)遠(yuǎn)高于Hibernate方式,且在數(shù)據(jù)量增長(zhǎng)的情況下耗時(shí)的增長(zhǎng)速度處于合理的區(qū)間內(nèi)。


    網(wǎng)頁(yè)名稱(chēng):Hibernate框架中直接操作JDBC接口實(shí)例
    URL分享:
    http://www.5511xx.com/article/dphiccj.html