Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > Java > CowNew开源学习文档-hibernate 的HQL源码分析1
【标  题】:CowNew开源学习文档-hibernate 的HQL源码分析1
【关键字】:CowNew,hibernate,HQL
【来  源】:http://www.blogjava.net/huanzhugege/archive/2006/06/02/49827.html

CowNew开源学习文档-hibernate 的HQL源码分析1

Your Ad Here

作者杨中科

CowNew 开源团队网站 http://www.cownew.com

论坛 http://www.cownew.com/newpeng/?

转载请保留此信息

一、HQL代码的构建。
(1)首先将hibernate中的src目录下的代码解压。
(2)安装配置好antlr。
(3)把grammar目录下的三个.g文件(hql.g,hql-sql.g,sql-gen.g)解压到一个目录,然后从命令行进入此目录,依次运行"java antlr.Tool hql.g","java antlr.Tool hql-sql.g","java antlr.Tool sql-gen.g",将生成的java代码拷贝到源代码的org.hibernate.hql.antlr下。
二、让我们从QueryTranslatorImpl开始分析,当调用session.find('...')的时候将会调用QueryTranslatorImpl的compile方法来解析hql语句为sql语句。compile则主要是调用的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();
}

可以看到主要是三步:调用parse方法将hql解析成AST,调用analyze根据上一步生成的AST生成SQLAST,调用generate根据上一步生成的SQL AST生成sql语句, 调用w.getSelectClause()就得到sql语句了。
“用parser把ast抽取出来,再用treeparser进行动作的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转化为sql ast,将生成模块与hibernate解耦。
?? 3.sql-gen.g 定义tree walker,从sql ast生成sql
”-《看Hibernate3如何解释HQL语言》
2、
逐步分析:
(1)parse方法:
HqlParser是从hql.g生成的HqlBaseParser继承来的,主要实现了HqlBaseParser定义的几个模版方法,传入的是hql语句,传出的是HQL AST。
(2)analyze:
HqlSqlWalker是从hql-sql.g生成的HqlSqlBaseWalker继承来的,HqlSqlBaseWalker又是从TreeParser继承的,主要实现了HqlSqlBaseWalker定义的几个模版方法,传入的是HQL AST,传出的是SQL AST。
hql-sql.g比hql.g简单许多了,因为hql-sql.g已经为我们生成了HQL AST了,hql-sql.g需要做的就是把HQL AST组装成强类型的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" );
?}
?;
这里主要就是在调用模版方法拼状强类型的SQL AST(异构AST)。所有的节点都定义在org.hibernate.hql.ast.tree中。
与第一部的HqlParser用户几乎不用写任何代码相反,我们需要完成我们从HqlSqlBaseWalker继承来的HqlSqlWalker的那些模版方法。
(3)generate方法:
遍历SQL AST,输出sql语句。SqlGenerator是从sql-gen.g生成的SqlGeneratorBase继承来的。输入的是SQL AST,输出的是SQL语句。我个人认为这一步也可以通过全部书写代码完成,可能更清晰,更灵活。
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("(");就是在拼装代码。

The End.:【上一篇】
Joel on software读书笔记一:【下一篇】
【相关文章】
  • Begin to learn hibernate
  • Hibernate的session用法
  • hibernate uuid.hex主键生成+spring带来的困惑
  • 关于Hibernate的DetachedCriteria查询的addOrder问题的解决办法
  • 做开源向雷锋同志学习-CowNew团队起航随感
  • JavaServer Faces(JSF)、Spring Framework和Hibernate建立
  • Eclipse下Hibernate的开发(一)入门实例
  • Eclipse下Hibernate的开发(二)利用Hbm映射文件开发
  • 关于Hibernate3的NativeSQL查询是如此简单
  • Spring in Action 笔记(III) -- 在Spring下的Hibernate数据操作
  • 【随机文章】
  • 热键和捕获系统菜单消息
  • 传奇世界 诸多活动之我见
  • google的一道JAVA面试题!!!
  • 模块常用的事务代码--PP(1)
  • 对你的ASP程序作负载测试
  • 高质量C&C++编程
  • 优化Windows内存使用效率
  • PL/SQL过程
  • 实战linux内核编译
  • 与afreez一起学习DirectFB之:framebuffer相关基础
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.