• 用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

     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

    魔由心生,有万境纵横,无一道清静,无量寿佛!
  • 相关阅读:
    python学习之路(目录)--你想要的都在这里了
    计算机视觉学习之路(目录)------你想要的都在这里了
    python flask构建小程序订餐系统--centos下项目开发环境的搭建
    图像处理--图像特效
    数据库--初识数据库
    python基础-面向对象进阶
    JavaScript 模块封装
    JavaScript calss语法糖
    JavaScript 原型与继承
    JavaScript Object对象
  • 原文地址:https://www.cnblogs.com/qihuan/p/3866264.html
Copyright © 2020-2023  润新知