用Hibernate框架把hql生成可执行的sql语句-Oracle方言

  引言:为什么这样的需求,源自公司项目需要,公司的项目使用java的struts2+spring2.5+oracle中间件tuxedo,数据库用的是Oracle,但由于不直接连接数据库,用中间件处理的方式,又不希望有太多服务,所以就开始网络找资料整理编码了。大概花了一个多星期完成了这个任务,现在整理出来与大家分享,也是自己知识的梳理。

  1.需要导入相关的jar: [按字母顺序排列]

antlr-2.7.5H3.jar           语言转换工,Hibernate利用它实现 HQL 到 SQL的转换

asm.jar               ASM 字节转换库

cglib-2.1.2.jar             高效的代码生成工具, Hibernate用它在运行时扩展 Java类和实现 Java 接口

classes12.jar              Oracle数据库驱动

commons-collections-2.1.1.jar      Apache 的工具集,用来增强Java对集合的处理能力

commons-logging-1.0.4.jar        Apache 软件基金组所提供的日志工具

dom4j-1.6.1.jar               dom4j XML 解析器

hibernate.jar                  Hibernate的核心库

jta.jar                      标准的 JAVA 事务处理接口

2. 在项目src 下加入 hibernate.cfg.xml ,并配置

 配置数据库方言dialect,和实体映射文件mapping,其他属性可以不用配置,因为不需要用到,注意:数据库连接url 不要加,因为加了后,程序会试图去连接。

 1 <?xml version=‘1.0‘ encoding=‘UTF-8‘?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3           "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4           "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 5
 6 <!-- Generated by MyEclipse Hibernate Tools.                   -->
 7 <hibernate-configuration>
 8 <session-factory>
 9     <!--  因为项目只需用Hibernate把hql转换成sql,包括无参数,有参数及需要格式化的参数
10     <property name="connection.url">
11         jdbc:oracle:thin:@127.0.0.1:1521:javacrm
12     </property>
13     <property name="connection.username">scott</property>
14     <property name="connection.password">tiger</property>
15     <property name="connection.driver_class">
16         oracle.jdbc.driver.OracleDriver
17     </property>
18     <property name="show_sql">true</property>
19     <property name="format_sql">true</property>
20     -->
21     <!-- 数据库方言 -->
22     <property name="dialect">
23         org.hibernate.dialect.Oracle10gDialect
24     </property>
25     <!-- 实体映射文件 -->
26     <mapping resource="com/test/bean/Student.hbm.xml"/>
27     <mapping resource="com/test/bean/BasDicConstant.hbm.xml"/>
28
29 </session-factory>
30 </hibernate-configuration>

3. 编写获取Session公共类 DbUtil.java

 

4. 编写核心转换类 HqlToSql.java

  1 package com.test.hqlc;
  2
  3 import java.util.Collections;
  4 import java.util.List;
  5
  6 import org.hibernate.Session;
  7 import org.hibernate.hql.ast.QueryTranslatorImpl;
  8 import org.hibernate.impl.SessionFactoryImpl;
  9
 10 import com.test.util.DbUtil;
 11
 12 /**
 13  * 传入hql语句,参数值列表,返回可执行的sql语句
 14  * @author xiufen.huang by 2014-07-03
 15  */
 16 public class HqlToSql {
 17
 18     /**
 19      * 处理结果信息,成功:为空,失败:错误信息
 20      */
 21     private static String resultMsg = "" ;
 22     private static final String nullMsg = "传入的hql为null或空!";
 23
 24     /**
 25      * 获取处理结果信息,成功:为空,失败:错误信息
 26      * @return 处理结果信息
 27      */
 28     public static String getResultMsg() {
 29         return resultMsg;
 30     }
 31
 32     /**
 33      * 将hql语句转换为sql语句,无参数
 34      * @param hql 要转换的hql语句
 35      * @return 可执行的sql语句,当返回null,可以通过getResultMsg()方法查看处理结果信息
 36      */
 37     public static String transHqlToSql(String hql){
 38         // 当hql为null或空时,直接返回null
 39         if (hql == null || hql.equals("")) {
 40             resultMsg = nullMsg;
 41             return null;
 42         }
 43         // 获取当前session
 44         Session session = DbUtil.currentSession();
 45         // 得到session工厂实现类
 46         SessionFactoryImpl sfi = (SessionFactoryImpl)session.getSessionFactory();
 47         // 得到Query转换器实现类
 48         QueryTranslatorImpl queryTranslator = new QueryTranslatorImpl(hql, hql, Collections.EMPTY_MAP, sfi);
 49         queryTranslator.compile(Collections.EMPTY_MAP, false);
 50         // 得到sql
 51         String sql = queryTranslator.getSQLString();
 52         // 关闭session
 53         DbUtil.closeSession();
 54         return sql;
 55     }
 56
 57     /**
 58      * 将hql语句转换为sql语句,不需要格式化参数的情况
 59      * @param hql 要转换的hql语句
 60      * @param paramValues hql参数值列表,注意与参数的顺序一致
 61      * @return 可执行的sql语句,当返回null,可以通过getResultMsg()方法查看处理结果信息
 62      */
 63     public static String transHqlToSql(String hql,List paramValues){
 64         // 要返回的sql语句
 65         String sql = transHqlToSql(hql);
 66         // 当为null或空时,返回null
 67         if (sql == null || sql.equals("")) {
 68             resultMsg = nullMsg;
 69             return null;
 70         }
 71
 72         // 赋参数值
 73         if (paramValues != null && paramValues.size() > 0) {
 74             for (int i = 0; i < paramValues.size(); i++) {
 75                 sql = sql.replaceFirst("\\?", "\\‘"+paramValues.get(i).toString()+"\\‘");
 76             }
 77         }
 78         return sql;
 79     }
 80
 81     /**
 82      * 将hql语句转换为sql语句,有日期,Char等需要格式化参数的情况
 83      * @param hql 要转换的hql语句
 84      * @param paramValues hql参数值列表,注意与参数的顺序一致
 85      * @return 可执行的sql语句,当返回null,可以通过getResultMsg()方法查看处理结果信息
 86      */
 87     public static String formatHqlToSql(String hql,List<TransTemp> paramValues){
 88         // 要返回的sql语句
 89         String sql = transHqlToSql(hql);
 90         // 当为null或空时,返回null
 91         if (sql == null || sql.equals("")) {
 92             resultMsg = nullMsg;
 93             return null;
 94         }
 95
 96         // 赋参数值
 97         if (paramValues != null && paramValues.size() > 0) {
 98             for (int i = 0; i < paramValues.size(); i++) {
 99                 TransTemp tt = paramValues.get(i);
100                 sql = sql.replaceFirst("\\?", tt.getOracleFormatString());
101             }
102         }
103         return sql;
104     }
105
106 }

5.测试实例 HqlToSqlTest.java

 1 package com.test.hqlc;
 2
 3 import java.text.SimpleDateFormat;
 4 import java.util.ArrayList;
 5 import java.util.Date;
 6 import java.util.HashMap;
 7 import java.util.List;
 8 import java.util.Map;
 9 import java.sql.Types;
10
11 import org.hibernate.Query;
12 import org.hibernate.Session;
13
14 import com.test.bean.Student;
15 import com.test.bean.BasDicConstant;
16 import com.test.util.DbUtil;
17
18 public class HqlToSqlTest {
19
20     public static void main(String[] args) {
21
22 //        String hql = "from Student";
23         String hql = "from Student where studentName like :stuName and birthDay between :dat1 and :dat2";
24
25
26         List vals = new ArrayList();
27         vals.add("%L%");
28         vals.add("1990-02-28 00:00:00");
29         vals.add("1992-02-28 23:59:59");
30
31         String sql1 = HqlToSql.transHqlToSql(hql);
32         System.out.println("hql转换成sql无参数:"+sql1);
33
34         String sql2 = HqlToSql.transHqlToSql(hql, vals);
35
36         System.out.println("hql转换成sql有参数:"+sql2);
37         System.out.println("转换结果信息: "+HqlToSql.getResultMsg());
38
39         // 有格式化字符串
40         List<TransTemp> list = new ArrayList<TransTemp>();
41
42         // 构造参数
43         TransTemp tt1 = new TransTemp();
44         tt1.setParamSqlType(Types.VARCHAR);
45         tt1.setParamValue("%L%");
46         list.add(tt1);
47
48         TransTemp tt2 = new TransTemp(Types.TIME,"1990-02-28 00:00:00");
49         list.add(tt2);
50
51         TransTemp tt3 = new TransTemp(Types.DATE,new Date(),"yyyy-mm-dd hh24:mi:ss");
52         list.add(tt3);
53
54         String tSql = HqlToSql.formatHqlToSql(hql, list);
55         System.out.println("hql转换成格式化参数的sql: "+tSql);
56
57     }
58 }

6.测试结果:

1 hql转换成sql无参数:select student0_.student_id as student1_0_, student0_.student_name as student2_0_, student0_.student_age as student3_0_, student0_.status as status0_, student0_.birth_Day as birth5_0_ from students student0_ where (student0_.student_name like ?) and (student0_.birth_Day between ? and ?)
2 hql转换成sql有参数:select student0_.student_id as student1_0_, student0_.student_name as student2_0_, student0_.student_age as student3_0_, student0_.status as status0_, student0_.birth_Day as birth5_0_ from students student0_ where (student0_.student_name like ‘%L%‘) and (student0_.birth_Day between ‘1990-02-28 00:00:00‘ and ‘1992-02-28 23:59:59‘)
3 转换结果信息:
4 hql转换成格式化参数的sql: select student0_.student_id as student1_0_, student0_.student_name as student2_0_, student0_.student_age as student3_0_, student0_.status as status0_, student0_.birth_Day as birth5_0_ from students student0_ where (student0_.student_name like ‘%L%‘) and (student0_.birth_Day between to_date(‘1990-02-28 00:00:00‘,‘yyyy-mm-dd hh24:mi:ss‘) and to_date(‘2014-07-24 17:21:38‘,‘yyyy-mm-dd hh24:mi:ss‘))

7. 参考资料:

http://coffeelover.iteye.com/blog/462139
http://blog.csdn.net/w_l_j/article/details/7064416
http://www.cnblogs.com/yql1986/archive/2011/09/30/2196621.html?ADUIN=416455569&ADSESSION=1404434624&ADTAG=CLIENT.QQ.5329_.0&ADPUBNO=26349

8.源码 Hibernate02.rar

用Hibernate框架把hql生成可执行的sql语句-Oracle方言

时间: 2024-10-17 13:44:47

用Hibernate框架把hql生成可执行的sql语句-Oracle方言的相关文章

EF-记录程序自动生成并执行的sql语句日志

在EntityFramework的CodeFirst模式中,我们想将程序自动生成的sql语句和执行过程记录到日志中,方便以后查看和分析. 在EF的6.x版本中,在DbContext中有一个Database属性,Database.Log就是用来专门记录这种日志的. Database.Log是一个Action<string>委托,给其赋值一个函数就行. 代码如下: using Model; using System; using System.Collections.Generic; using

怎样在控制台或者日志打印输出JDBC执行的sql语句

今天用jdbc preparestatement 写sql语句查询,但是在执行的过程中实际查询出的结果和预期的结果不一致,然后就在想有什么办法能够在控制台或者Log4j日志输出最终执行的SQL语句,以便于调试.如果是hibernate可以通过配置show_sql 为 true 在控制台显示执行的SQL,因为使用的是纯JDBC的写法,然后自己在程序中直接通过System.out.println(sql);打印SQL语句,然后又打印参数,这种方式确实是可以.但是,遇到insert语句或者Update

存储过程中执行动态Sql语句

存储过程中执行动态Sql语句 MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就是利用sp_executesql,能够重用执行计划,这就大大提供了执行性能,还可以编写更安全的代码.EXEC在某些情况下会更灵活.除非您有令人信服的理由使用EXEC,否侧尽量使用sp_executesql. 1.EXEC的使用 EXEC命令有两种用法,一种是执行一个存储

laravel中查看执行的SQL语句

今天想查看laravel框架中执行的SQL语句,百度了一圈,才找到,这文档真心看着不爽,下面上查看方法 DB::connection()->enableQueryLog(); $navObj = new NavModel(); $data = $navObj->where($where)->select($this->field)->orderBy('id', 'desc') ->get(); $log = DB::getQueryLog(); dd($log); di

使用Oracle的DBMS_SQL包执行动态SQL语句

使用Oracle的DBMS_SQL包执行动态SQL语句 引用自:http://blog.csdn.net/ggjjzhzz/archive/2005/10/17/507880.aspx 引用自:http://www.cnblogs.com/simonhaninmelbourne/archive/2013/01/23/2872438.html 在某些场合下,存储过程或触发器里的SQL语句需要动态生成.Oracle的DBMS_SQL包可以用来执行动态SQL语句.本文通过一个简单的例子来展示如何利用D

生成表记录的SQL语句

/*------------------------------------------------------------------------------- 功能:     生成表记录的SQL语句(注TEXT与NTEXT字段导出为NULL) 参数说明:     @Table_Name   表名     @IsPrint         是否打印输入[1:是,0:否].                     是:Print字符串在查询分析器中使用.                    

查看Mysql实时执行的Sql语句

最近给客户开发了基于Asp.Net mvc5 +Mysql+EF的项目,但是在EF里无法看到Mysql执行的语句 之前也找到一些监控Mysql的软件但一直没有用起来,现在又遇到了问题即在EF里Mysal的查询没有结果而在Mysql里没有问题 因为不知道EF生成的Mysql语句所以不知道是不是Sql的问题于是决定必须解决此问题 通过半天时间的努力解决了此问题,其实很简单即开启Mysql的Log功能,那么Mysql的执行语句都会写到Log文件里 然后通过BareTail这个专门查看Log文件的工具即

Sql Server 查看当前正在执行的Sql 语句

查看Sql Server 当前正在执行的Sql 语句,可以使用 sys.sysprocesses 或 sys.dm_exec_requests,由于sys.sysprocesses是为了向后兼容而保留的,所以,推荐使用DMV:sys.dm_exec_requests 一,使用sys.sysprocesses Contains information about processes that are running on an instance of SQL Server. These proce

LoadRunner 执行单句SQL语句

LoadRunner 执行单句SQL语句 Action() { int NumRows=0; int i=1; //建立数据库连接 lr_db_connect("StepName=DatabaseConnection", "ConnectionString=Provider=SQLOLEDB.1;Password=***;Persist Security Info=True;User ID=sc;Initial Catalog=EGMIS_NET;Data Source=19