<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    如鵬網(wǎng) 大學(xué)生計(jì)算機(jī)學(xué)習(xí)社區(qū)

    CowNew開源團(tuán)隊(duì)

    http://www.cownew.com 郵件請聯(lián)系 about521 at 163.com

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      363 隨筆 :: 2 文章 :: 808 評論 :: 0 Trackbacks

    作者楊中科

    CowNew 開源團(tuán)隊(duì)網(wǎng)站 http://www.cownew.com

    論壇 http://www.cownew.com/newpeng/?

    轉(zhuǎn)載請保留此信息

    一、HQL代碼的構(gòu)建。
    (1)首先將hibernate中的src目錄下的代碼解壓。
    (2)安裝配置好antlr。
    (3)把grammar目錄下的三個.g文件(hql.g,hql-sql.g,sql-gen.g)解壓到一個目錄,然后從命令行進(jìn)入此目錄,依次運(yùn)行"java antlr.Tool hql.g","java antlr.Tool hql-sql.g","java antlr.Tool sql-gen.g",將生成的java代碼拷貝到源代碼的org.hibernate.hql.antlr下。
    二、讓我們從QueryTranslatorImpl開始分析,當(dāng)調(diào)用session.find('...')的時候?qū){(diào)用QueryTranslatorImpl的compile方法來解析hql語句為sql語句。compile則主要是調(diào)用的doCompile方法。
    // PHASE 1 : Parse the HQL into an AST.
    HqlParser parser = parse( true );

    // PHASE 2 : Analyze the HQL AST, and produce an SQL AST.
    HqlSqlWalker w = analyze( parser, collectionRole );
    sqlAst = ( Statement ) w.getAST();
    generate( ( QueryNode ) sqlAst );
    queryLoader = new QueryLoader( this, factory, w.getSelectClause() );

    parse的主要代碼:
    private HqlParser parse(boolean filter)
    ?HqlParser parser = HqlParser.getInstance( hql );
    ?parser.statement();
    ?AST hqlAst = parser.getAST();
    ??return parser;
    }
    analyze的主要代碼:
    private HqlSqlWalker analyze(HqlParser parser, String collectionRole) throws QueryException, RecognitionException {
    ?HqlSqlWalker w = new HqlSqlWalker( this, factory, parser, tokenReplacements, collectionRole );
    ?AST hqlAst = parser.getAST();
    ?w.statement( hqlAst );
    ?return w;
    }
    generate的主要代碼:
    private void generate(AST sqlAst) throws QueryException, RecognitionException {
    ?SqlGenerator gen = new SqlGenerator(factory);
    ?gen.statement( sqlAst );
    ?sql = gen.getSQL();
    }

    可以看到主要是三步:調(diào)用parse方法將hql解析成AST,調(diào)用analyze根據(jù)上一步生成的AST生成SQLAST,調(diào)用generate根據(jù)上一步生成的SQL AST生成sql語句, 調(diào)用w.getSelectClause()就得到sql語句了。
    “用parser把a(bǔ)st抽取出來,再用treeparser進(jìn)行動作的double pass builder模式,解耦了parser和generation,再配合template,是antlr推薦的最佳模式。”-《看Hibernate3如何解釋HQL語言》
    1、三個語法文件的作用:

    hibernate的hql grammar文件一共有三個,在/grammar目錄下:
    ?? 1.hql.g?? 定義token類和parser類,將hql解釋成hql的抽象語法樹(ast)
    ?? 2.hql-sql.g? 定義tree walker ,將hql ast轉(zhuǎn)化為sql ast,將生成模塊與hibernate解耦。
    ?? 3.sql-gen.g 定義tree walker,從sql ast生成sql
    ”-《看Hibernate3如何解釋HQL語言》
    2、
    逐步分析:
    (1)parse方法:
    HqlParser是從hql.g生成的HqlBaseParser繼承來的,主要實(shí)現(xiàn)了HqlBaseParser定義的幾個模版方法,傳入的是hql語句,傳出的是HQL AST。
    (2)analyze:
    HqlSqlWalker是從hql-sql.g生成的HqlSqlBaseWalker繼承來的,HqlSqlBaseWalker又是從TreeParser繼承的,主要實(shí)現(xiàn)了HqlSqlBaseWalker定義的幾個模版方法,傳入的是HQL AST,傳出的是SQL AST。
    hql-sql.g比hql.g簡單許多了,因?yàn)閔ql-sql.g已經(jīng)為我們生成了HQL AST了,hql-sql.g需要做的就是把HQL AST組裝成強(qiáng)類型的SQL AST,此處大量引用了hql.g中定義的Vocabulary。
    比如:
    query!
    ?: #( QUERY { beforeStatement( "select", SELECT ); }
    ???// The first phase places the FROM first to make processing the SELECT simpler.
    ???#(SELECT_FROM
    ????f:fromClause
    ????(s:selectClause)?
    ???)
    ???(w:whereClause)?
    ???(g:groupClause)?
    ???(o:orderClause)?
    ??) {
    ??// Antlr note: #x_in refers to the input AST, #x refers to the output AST
    ??#query = #([SELECT,"SELECT"], #s, #f, #w, #g, #o);
    ??beforeStatementCompletion( "select" );
    ??processQuery( #s, #query );
    ??afterStatementCompletion( "select" );
    ?}
    ?;
    這里主要就是在調(diào)用模版方法拼狀強(qiáng)類型的SQL AST(異構(gòu)AST)。所有的節(jié)點(diǎn)都定義在org.hibernate.hql.ast.tree中。
    與第一部的HqlParser用戶幾乎不用寫任何代碼相反,我們需要完成我們從HqlSqlBaseWalker繼承來的HqlSqlWalker的那些模版方法。
    (3)generate方法:
    遍歷SQL AST,輸出sql語句。SqlGenerator是從sql-gen.g生成的SqlGeneratorBase繼承來的。輸入的是SQL AST,輸出的是SQL語句。我個人認(rèn)為這一步也可以通過全部書寫代碼完成,可能更清晰,更靈活。
    selectExpr
    ?: e:selectAtom { out(e); }
    ?| count
    ?| #(CONSTRUCTOR (DOT | IDENT) ( selectColumn )+ )
    ?| methodCall
    ?| aggregate
    ?| c:constant { out(c); }
    ?| arithmeticExpr
    ?| PARAM { out("?"); }
    ?| sn:SQL_NODE { out(sn); }
    ?| { out("("); } selectStatement { out(")"); }
    其中的out("(");就是在拼裝代碼。

    posted on 2006-06-02 00:56 CowNew開源團(tuán)隊(duì) 閱讀(4974) 評論(2)  編輯  收藏

    評論

    # re: CowNew開源學(xué)習(xí)文檔-h(huán)ibernate 的HQL源碼分析1 2006-06-02 10:03 人要有夢想
    其實(shí)說白了就是使用antlr做詞法語法分析。
    HQL->HQL AST->SQL AST->SQL  回復(fù)  更多評論
      

    # re: CowNew開源學(xué)習(xí)文檔-h(huán)ibernate 的HQL源碼分析1 2007-06-29 09:56 大灰狼
    小弟請教一個問題: 在oracle中有一個NUMBER(2)字段,里面有一個記錄存有值2;現(xiàn)寫一個hql語句,.....where typelevel=2或typelevel<>2為什么都不起作用,要不該怎么寫?  回復(fù)  更多評論
      


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 特色特黄a毛片高清免费观看| 亚洲视频小说图片| 深夜a级毛片免费视频| 免费A级毛片无码无遮挡内射| 久久久久亚洲AV无码专区体验| 国产一区二区三区免费观看在线| 亚洲午夜无码片在线观看影院猛| 无套内射无矿码免费看黄| 免费少妇a级毛片| h视频免费高清在线观看| 亚洲热线99精品视频| 久久免费福利视频| 亚洲精品美女在线观看| 在线观看成人免费视频不卡| 亚洲伊人久久大香线蕉AV| 日韩在线看片免费人成视频播放| 免费亚洲视频在线观看| 亚洲色偷偷偷鲁综合| 蜜桃视频在线观看免费视频网站WWW| 亚洲精品午夜久久久伊人| 18禁超污无遮挡无码免费网站国产| 亚洲色大18成人网站WWW在线播放| 国产免费人成视频在线观看| 一区二区在线免费视频| 亚洲av日韩av高潮潮喷无码 | 亚洲精品第一国产综合精品99| 在线播放免费人成视频网站| 亚洲人成中文字幕在线观看| 久久国产色AV免费观看| 亚洲欧美aⅴ在线资源| 亚洲天堂免费在线视频| **实干一级毛片aa免费| 亚洲av无码av在线播放| 国产亚洲免费的视频看| 色se01短视频永久免费| 小说区亚洲自拍另类| 亚洲黄色网址在线观看| 国产成人涩涩涩视频在线观看免费 | 亚洲综合色视频在线观看| 114级毛片免费观看| 日韩在线视频线视频免费网站|