用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方言的更多相关文章
- EF-记录程序自动生成并执行的sql语句日志
在EntityFramework的CodeFirst模式中,我们想将程序自动生成的sql语句和执行过程记录到日志中,方便以后查看和分析. 在EF的6.x版本中,在DbContext中有一个Databa ...
- 使用Mysql中的concat函数或正则匹配来快速批量生成用于执行的sql语句
背景介绍 今天需要给一张表里面补数据,需要按照行的维度进行update,如果是个别数据那么直接写update语句就可以了,但是场景要求的是将整表的数据进行update,要实现这个需求就不能只靠蛮力了, ...
- java:Hibernate框架3(使用Myeclipse逆向工程生成实体和配置信息,hql语句各种查询(使用hibernate执行原生SQL语句,占位符和命名参数,封装Vo查询多个属性,聚合函数,链接查询,命名查询),Criteria)
1.使用Myeclipse逆向工程生成实体和配置信息: 步骤1:配置MyEclipse Database Explorer: 步骤2:为项目添加hibernate的依赖: 此处打开后,点击next进入 ...
- [LINQ2Dapper]最完整Dapper To Linq框架(五)---查看Linq实际执行的SQL
此例子是使用LINQ2Dapper封装,效率优于EntityFramwork,并且支持.NetFramework和.NetCore框架,只依赖于Dapper支持.net framework4.6.1及 ...
- 出错场景是升级oracle驱动,将版本从ojdbc14升级到ojdbc6,hibernate执行原生态sql语句会报如下错误
出错场景是升级oracle驱动,将版本从ojdbc14升级到ojdbc6,hibernate执行原生态sql语句会报如下错误:org.hibernate.MappingException: No Di ...
- django框架 - 实时查看执行的sql语句
django框架采用的ORM模型,我们可以通过mysql的日志记录实时看到执行的sql语句,具体步骤如下: 第一步:找到mysql的配置文件 第二步:编辑mysql配置文件 第三步:重启mysql 第 ...
- thinkPHP框架中执行原生SQL语句的方法
这篇文章主要介绍了thinkPHP框架中执行原生SQL语句的方法,结合实例形式分析了thinkPHP中执行原生SQL语句的相关操作技巧,并简单分析了query与execute方法的使用区别,需要的朋友 ...
- EF 记录执行的sql语句
最近做了个中等的项目,数据不会很多,开发时间比较紧迫,所以用了EF的框架. 在使用过程中,发现有时候执行的结果不如预期,想看看执行的sql语句为何,遍查找资料,在网上找到了相关辅助类,拿来使用,部署到 ...
- 2016/05/13 thinkphp 3.2.2 ① 数据删除及执行原生sql语句 ②表单验证
[数据删除及执行原生sql语句] delete() 返回受影响的记录条数 $goods -> delete(30); 删除主键值等于30的记录信息 $goods -> delete( ...
随机推荐
- 利用idea的code inspect功能进行代码静态分析
利用idea.phpstorm系列的ide的code inspect功能可以开发出适用于各种编程语言的代码静态分析工具.这个功能大家可以自己实现扩展规则,规则也使用了visitor模式,规则里对关心的 ...
- 本书版权输出到台湾地区,《深入理解Android内核设计思想》诚挚感谢大家一直以来的支持!
- js如何打印对象
js调试中经常会碰到输出的内容是对象而无法打印的时候,光靠alert只能打印出object标示,却不能打印出来里面的内容,甚是不方便,于是各方面整理总结了如下一个函数,能够将数组或者对象这类的结果一一 ...
- 打开的文件符合PDF/A标准,且已在只读模式下打开,以防被修改
PDF/A是一种用于长期归档和保留电子文档的ISO标准.您扫描到PDF的文档符合PDF/A的规范.您可以指定是否要用本查看模式查看文档. PDF/A 问题提示:“打开的文件符合PDF/A标准,且已在只 ...
- phpcms v9模板制作常用代码集合
phpcms v9模板制作常用代码集合(个人收藏) 1.截取调用标题长度 {str_cut($r[title],36,'')} 2.格式化时间 调用格式化时间 2011-05-06 11:22:33 ...
- es6的Set和Map数据结构
Set 和 Map 数据结构 Set WeakSet Map WeakMap Set § ⇧ 基本用法 ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set ...
- Connecting to a Remote Serial Port over TCP/IP
https://www.acmesystems.it/socat This article illustrates how to realize a lan to serial gateway Rem ...
- java.lang.ClassFormatError: Trjava.lang.ClassFormatError: Truncated class fileuncated class file
周末过来加班,上传编译好的文件后,部署到服务器没事.但是服务器日志满了,把日志清除后,把服务启动,发现报这个错误,大致网上看了一下,这个错误是编译的文件损坏了.然后大致看了一下文件,还真是.由于日志满 ...
- linux lanmp一件安装包
转载地址:http://lamp.phpstudy.net/ phpStudy Linux版&Win版同步上线 支持Apache/Nginx/Tengine/Lighttpd/IIS7/8/6 ...
- char、varchar与text
总结自:https://www.cnblogs.com/mjbrian/p/6866263.html char: 定长,长度范围是0~255. 当长度不足255时,用空格来填充剩下的字符. ...