首页 > 代码库 > 用Hibernate框架把hql生成可执行的sql语句-Oracle方言

用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:javacrm12     </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.OracleDriver17     </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.Oracle10gDialect24     </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

 1 package com.test.util; 2  3 import org.hibernate.HibernateException; 4 import org.hibernate.Session; 5 import org.hibernate.SessionFactory; 6 import org.hibernate.cfg.Configuration; 7  8 public class DbUtil { 9 10     private static final SessionFactory sessionFactory;11     public static final ThreadLocal session = new ThreadLocal();12 13     static {14         try {15             sessionFactory = new Configuration().configure()16                     .buildSessionFactory();17         } catch (Throwable ex) {18             ex.printStackTrace();19             throw new ExceptionInInitializerError(ex);20         }21     }22 23     public static Session currentSession() throws HibernateException {24         Session s = (Session) session.get();25         if (s == null || !s.isOpen()) {26             s = sessionFactory.openSession();27             session.set(s);28         }29         return s;30     }31 32     public static void closeSession() throws HibernateException {33         Session s = (Session) session.get();34         session.set(null);35         if (s != null)36             s.close();37     }38 39     public SessionFactory getSessionFactory() {40         return sessionFactory;41     }42     43 }
View Code

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