首页 > 代码库 > 用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 }
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