`
ye_wx
  • 浏览: 13202 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

hibernate外连接原理

阅读更多

最近接手了一个要维护的项目,是用Hibernate2+Oralce8写成的,因为看到Hibernate3页出来这么久了,而且也感觉Hibernate3有它的许多新的特性,如批量删除和更新,新的HQL语法解析器AST。

升级过程大致按照孙卫琴的那篇文章 如何把Hibernate2.1升级到Hibernate3.0?来做,该替换的替换完,该设置的设置完,程序一跑,当程序执行到向下面这种查询的时候(Oracle所特有的外连接查询),报错。

语句为:(描述为类似语句,把项目中的实际表名隐去了)

session.createQuery("select t1.c1,t2.c1 from Table1 t1,Table2 t2 where t1.c1=t2.c1(+)").list();

出错信息为:
org.hibernate.hql.ast.QuerySyntaxException: unexpected token: ) near line 1, column 106 [select t1.c1,t2.c1 from Table1 t1,Table2 t2 where t1.c1=t2.c1(+)]
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:31)
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:24)
at org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:59)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:258)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:157)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:111)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)

再回头看看孙卫琴的那篇升级注意事项中 1.3 查询语句的变化 提到Hibernate3.0 采用新的基于ANTLR的HQL/SQL查询翻译器ASTQueryTranslator,它已经不支持像Oracle8i和Sybase11那样的 THETA-STYLE 连接查询方言。

解决这一问题的办法有两种:
(1)改为使用支持ANSI-STYLE连接查询的方言,像 LEFT OUTER JOIN .. ON ..的写法
(2)也可改用 Hibernate2的查询翻译器,可在 hibernate.cfg.xml 中进行配置。

因第一种方法,需要在映射文件中配置PO 间的X 对X的关联关系才能用,如过哪位朋友在不配置 PO 间关联关系时也能用LEFT OUTER JOIN .. ON ..的写法连接查询,能告诉我怎么做的号吗?让咱也学一招,先谢了!

所以想想还是在 hibernate.cfg.xml 中配置

注:hibernate3默认的HQL语法翻译器的配置为:

使用传统的hibernat2所用的HQL语法翻译器。然后程序再跑一跑,刚刚那个(+)的地方是没有错了,可是新麻烦有冒起来了,程序执行到

session.createQuery("delete User u where u.name='Unmi'").executeUpdate();

有报错了:
org.hibernate.QueryException: query must begin with SELECT or FROM: delete [delete com.unmi.User where u.name='Unmi']

原来旧的HQL语法解析器不支持 delete User 的写法,hibernate2在删除持久化对象时必须写成

session.delete("delete User u where u.name='Unmi'");

然而新的 org.hibernate.Session 的接口方法已去除了 Session.delete(String hql)方法,看来这条路也是受阻了。正是两头受难,无奈之时暂时放弃了升级的念头,把该还原的地方都恢复旧模样了。

过了好一段时间,也就是个把月吧……

心里总也觉不甘心,觉得事情总有解决的办法,于是采用了终极办法:从原代码下手,进行单步的跟踪,看看hibernate3何时进行HQL到SQL的转换,何时取用配置的语法翻译器。

下面要解决的一个课题就是:

如何让Hibernate3既能使用新的Delete和Update语法,又能使用 Oracle Theta-Style 的 t1.c1=t2.c1(+)外连接写法

其中的语法翻译器如何把传入的一条HQL语句拆解进行分析这里就不详叙,不过最好还是要明白一点:
Classic语法翻译器会把传入的t1.c1=t2.c1(+)中的(+)作为一个整体,不拆开来,而AST语法分析器却会把其中的(+)依括号拆成 ”(” , ”+” , ”)”三部分。

我们首先来看看HQL语法翻译工厂接口 QueryTranslatorFatory 有两个接口方法:


调用以上两个方法只在类 HQLQueryPlan的构造函数中(五个参数的那个)

这个构造函数接收你写的HQL语句还有一个 SessionFactoryImplementor (extends SessionFactory),这个SessionFactory持有hibernate.cfg.xml的配置项HQL语法翻译器。
读这个构造函数的代码,我们发现有两段代码

它们的职能是获取SessionFactory (hibernate.cfg.xml)所配置的HQL语法分析器,这也就是我们的切入点,我们所希望的事情是:
当构造HQLQueryPlan时,发现传给的hql是一个Oracle 那样的THETA-STYLE 连接查询语句(即像有(+)那样的语句),我们就绕开在 hibernate.cfg.xml 所配置的AST HQL语法翻译器,而是采用能够理解这种语法的传统的语法翻译器。
因此我们只要把 HQLQueryPlan类的这个构造函数中的

if ( collectionRole == null) { …………………………… }

改为如下:


改完之后,把编译后的HQLQueryPlan.class覆盖到hibernate3.jar包中相应的目录中即可,或者把这个类放在classes下相应的目录中,在WEB应用程序中 WEB-INF/classes中的类是优先于jar包中的类先加载。
以上做法两种有些矛盾的问题也就得到解决了,org.hibernate.Session既可以执行Hibernate3 引入的 delete/update语句,还能够在 Oracle/Sybase中用(+)外连接方式而不需要配置X对X的连接关系。

下面再介绍一种折中的解决办法,不知大家注意到没有,在Hibernate3中的

org.hibernate.SessionFactory的openSession方法返回的是一个
org.hibernate.classic.Session对象,而org.hibernate.classic.Session是继承自org.hibernate.Session的。

public org.hibernate.classic.Session openSession(Connection connection);

public interface Session extends org.hibernate.Session

而通常我们顺应新潮流,是用org.hibernate.Session去引用SessionFactory的方法openSession()的返回值的,于是我们想用 session.delete(sql) 方法时,就把返回的Session实例转型为 org.hibernate.classic.Session即可。

((org.hibernate.classic.Session)session).delete("from User u where u.name='Unmi'");

如果你也想用原始Session的其他已被摈弃的方法,亦可如此这般做。

当然了,在另一方面要让Hibernate 能支持 Oracle/Sybase中用(+)外连接方式, 您还是要使

用传统的语法分析器,他将不能理解新的delete/update语句,很遗憾。
所以为了顺应新的潮流的发展,应使用第一种方法。要知道hibernate3中的delete/update语句可比2中的session.delete(hql)方法效率高,hibernate3中直接向数据库发一个delete语句,而在hibernate2中的delete(hql)方法是需要首先加载对象在删除,确有些多次一举,不过又是也有它的道理,update也类此。

在补充一个:hibernate会对 hql 对应的 HQLQueryPlan 进行缓冲的,在类 QueryPlanCache 中处理


依据queryString(hql)生成key值.

 

转自:http://blog.csdn.net/kypfos/article/details/1559554

分享到:
评论

相关推荐

    spring+struts+hibernate工作原理

    客户端不直接与数据库交互,而是通过组件与中间层建立连接,再由中间层与数据库交互。典型的J2EE三层结构,分为表现层、中间层(业务逻辑层)和数据服务层。三层体系将业务规则、数据访问及合法性校验等工作放在中间...

    hibernate资料

    hibernate 深入 连接 关联级映射,源码解析,spring 与hibernate的配置深入原理

    针对SSH框架Spring管理Hibernate连接多个数据源配置文件

    该配置文件连接的是两个数据库结构相同的数据源,其他比如数据库结构不原理也可行。本人在遇到此问题时上网搜了很多答案结果都不怎么如意,有的太深奥不过思想很好,有的又太不给力,后来自己慢慢研究配置成功后想与...

    SpringMVC+Hibernate+Spring

    通过整合网上分散资源,集成Spring3.03,Hibernate3,连接池c3p0,实现helloword小例子,和简单的登录功能。框架解释清晰,分享出来,后期持续更新。

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     16.3.6 迫切左外连接检索(fetch属性为“join”)  16.4 多对一和一对一关联的检索策略  16.4.1 迫切左外连接检索(fetch属性为“join”)  16.4.2 延迟检索(lazy属性为默认值“proxy”)  16.4.3 无代理延迟...

    基于Java数据库连接池的研究与创新

    本文首先介绍了传统连接、tomcat下连接池和hibernate下连接池的基本原理,然后在此基础上提出了一种改进的新型连接池方法,最后基于Java语言对四种连接方法进行了仿真模拟。通过实验测试及连接时间的对比分析,看到...

    weblogic,log4j,druid,hibernate,spring,struts2连接泄露检测

    weblogic,log4j,druid,hibernate,spring,struts2,hutoolDb,Oracle连接池配置,连接泄露检测及简要原理说明 连接关了关,怎么用druid检测

    Hibernate_ORM步骤详解

    以前全是手动写代码。以前自学ssh架构的时候还不知道Hibernate3能够根据数据库中的表自动生成相应的代码,今天看书时...他可以帮助我们更加深刻得了解Hibernate的持久化与ORM的原理及其实现。适合有一定基础的人学习。

    精通SSH的底层机制及原理

    精通SSH三大框架的底层机制及原理,介绍了spring,struts,hibernate等的原理

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     16.3.6 迫切左外连接检索(fetch属性为“join”)  16.4 多对一和一对一关联的检索策略  16.4.1 迫切左外连接检索(fetch属性为“join”)  16.4.2 延迟检索(lazy属性为默认值“proxy”)  16.4.3 无代理延迟...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     16.3.6 迫切左外连接检索(fetch属性为“join”)  16.4 多对一和一对一关联的检索策略  16.4.1 迫切左外连接检索(fetch属性为“join”)  16.4.2 延迟检索(lazy属性为默认值“proxy”)  16.4.3 无代理延迟...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     16.3.6 迫切左外连接检索(fetch属性为“join”)  16.4 多对一和一对一关联的检索策略  16.4.1 迫切左外连接检索(fetch属性为“join”)  16.4.2 延迟检索(lazy属性为默认值“proxy”)  16.4.3 无代理延迟...

    WEB中,各种技术的原理

    SSH、AJAX、线程安全、SERVLET等技术的原理和简单应用,共14个文档 1、ajax的原理.doc 2、Hibernate框架如何实现ORM.doc ...12、数据库连接池的工作原理.doc 13、线程安全.doc 14、详解jdbc和hibernate区别.doc

    Spring3+hibernate4+Struts2图书管理系统

    2.修改applicationContext.xml文件中hibernate.hbm2ddl.auto的值为create而不是update 3.修改数据库的连接信息(数据库,用户名,密码) 4.部署到Tomcat服务器上面,然后运行 5.在浏览器中输入...

    JDBC数据库编程实验

    一、实验目的: ...(5)理解数据库连接池的基本原理和思想,学会在tomcat服务器中配置数据库连接池,并掌握从连接池中获取连接的基本方法。 (6)初步理解数据访问层的基本设计方法,理解web的分层架构。

    Java求职面试宝典各大公司常考知识点

    1.1. Hibernate工作原理 2 1.2. 什么是Hibernate的并发机制?怎么处理并发问题? 2 1.3. Hibernate自带的分页机制是什么?如果不使用Hibernate自带的分页,则采用什么方式分页? 3 1.4. hibernate的对象的三种持久化...

    Spring Data JPA 原理与实战2021年

    │ 开篇词 勇敢走出舒适区,突破自己的技术瓶颈.mp4 ...│ 20 Spring JPA 中的 Hibernate 加载过程与配置项是怎么回事?.mp4 │ 21 Peritence Context 所表达的核心概念是什么?.mp4 │ 22 Seio

    Spring攻略(第二版 中文高清版).part2

    3.3 访问连接点信息 121 3.3.1 问题 121 3.3.2 解决方案 122 3.3.3 工作原理 122 3.4 指定aspect优先级 123 3.4.1 问题 123 3.4.2 解决方案 123 3.4.3 工作原理 123 3.5 重用切入点定义 125 3.5.1...

Global site tag (gtag.js) - Google Analytics