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

    魔由心生,有万境纵横,无一道清静,无量寿佛!
  • 相关阅读:
    hdu 6702 ^&^ 位运算
    hdu 6709 Fishing Master 贪心
    hdu 6704 K-th occurrence 二分 ST表 后缀数组 主席树
    hdu 1423 Greatest Common Increasing Subsequence 最长公共上升子序列 LCIS
    hdu 5909 Tree Cutting FWT
    luogu P1588 丢失的牛 宽搜
    luogu P1003 铺地毯
    luogu P1104 生日
    luogu P1094 纪念品分组
    luogu P1093 奖学金
  • 原文地址:https://www.cnblogs.com/qihuan/p/3866264.html
Copyright © 2020-2023  润新知