文档章节

解决Hibernate不支持PostgreSQL中双冒号(::)的问题

李玉珏
 李玉珏
发布于 2015/03/05 13:53
字数 620
阅读 2187
收藏 2
点赞 0
评论 6

        在PostgreSQL中,双冒号(::)的作用是类型转换,而在Hibernate中,SQL中冒号的作用是命名参数,用于SQL中命名参数的匹配,这时,当在PostgreSQL数据库环境中,正常的SQL本身包括双冒号时,通过Hibernate进行查询就会报错,这个应该是Hibernate的一个Bug,怎么解决呢,本文将给出方案。

        通过研究Hibernate的源代码,发现了问题所在,问题出在org.hibernate.engine.query.spi.ParameterParser,这个类构造方法为私有,包括若干个静态方法,无法通过扩展二次开发的方式解决,遇到这个问题的,只能自行修改Hibernate的源代码,然后编译。

        经过分析,只需要修改其中的parse方法即可,下面的代码即为修改后的代码,测试了一下,大体应该是没问题的,该问题的发现、开发、测试是在Hibernate4.2.15版本下进行的,其他版本如有问题,请开发者自行处理。

public static void parse(String sqlString, Recognizer recognizer) throws QueryException {
        boolean hasMainOutputParameter = startsWithEscapeCallTemplate( sqlString );
        boolean foundMainOutputParam = false;

        int stringLength = sqlString.length();
        boolean inQuote = false;
        for ( int indx = 0; indx < stringLength; indx++ ) {
            char c = sqlString.charAt( indx );
            if ( inQuote ) {
                if ( '\'' == c ) {
                    inQuote = false;
                }
                recognizer.other( c );
            }
            else if ( '\'' == c ) {
                inQuote = true;
                recognizer.other( c );
            }
            else if ( '\\' == c ) {
                // skip sending the backslash and instead send then next character, treating is as a literal
                recognizer.other( sqlString.charAt( ++indx ) );
            }
            else {
                if ( c == ':' ) {
                    // named parameter
                    int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS_BITSET, indx + 1 );
                    int chopLocation = right < 0 ? sqlString.length() : right;
                    //增加了双冒号的处理
                    if (sqlString.charAt( indx+1 ) != ':'){
                        String param = sqlString.substring( indx + 1, chopLocation );
                        if ( StringHelper.isEmpty( param ) ) {
                            throw new QueryException(
                                    "Space is not allowed after parameter prefix ':' [" + sqlString + "]"
                            );
                        }
                        recognizer.namedParameter( param, indx );
                        indx = chopLocation - 1;
                    }else{
                        recognizer.other(c);
                        recognizer.other(c);
                        indx++;
                    }
                }
                else if ( c == '?' ) {
                    // could be either an ordinal or JPA-positional parameter
                    if ( indx < stringLength - 1 && Character.isDigit( sqlString.charAt( indx + 1 ) ) ) {
                        // a peek ahead showed this as an JPA-positional parameter
                        int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS, indx + 1 );
                        int chopLocation = right < 0 ? sqlString.length() : right;
                        String param = sqlString.substring( indx + 1, chopLocation );
                        // make sure this "name" is an integral
                        try {
                            Integer.valueOf( param );
                        }
                        catch( NumberFormatException e ) {
                            throw new QueryException( "JPA-style positional param was not an integral ordinal" );
                        }
                        recognizer.jpaPositionalParameter( param, indx );
                        indx = chopLocation - 1;
                    }
                    else {
                        if ( hasMainOutputParameter && !foundMainOutputParam ) {
                            foundMainOutputParam = true;
                            recognizer.outParameter( indx );
                        }
                        else {
                            recognizer.ordinalParameter( indx );
                        }
                    }
                }
                else {
                    recognizer.other( c );
                }
            }
        }
    }

 

 

© 著作权归作者所有

共有 人打赏支持
李玉珏

李玉珏

粉丝 268
博文 57
码字总数 92115
作品 0
沈阳
技术主管
加载中

评论(6)

a
ayashaki

引用来自“liyuj”的评论

引用来自“ayashaki”的评论

引用来自“Tengern”的评论

为什么不进行转义呐,使用“\\:\\:”。 else if ( '\\' == c ) 这段代码会进行转义处理
为什么我转义了还是报错。。 Space is not allowed after parameter prefix ':' [select @rownum\:=@rownum+1 AS rownum 用的hibernate3.3.2

我这个是在hibernate4上代码,3上是怎么实现的,我不知道,你可以下个代码跟踪下
3估计没有,最后还是选择换sql语句了。。。
李玉珏
李玉珏

引用来自“ayashaki”的评论

引用来自“Tengern”的评论

为什么不进行转义呐,使用“\\:\\:”。 else if ( '\\' == c ) 这段代码会进行转义处理
为什么我转义了还是报错。。 Space is not allowed after parameter prefix ':' [select @rownum\:=@rownum+1 AS rownum 用的hibernate3.3.2

我这个是在hibernate4上代码,3上是怎么实现的,我不知道,你可以下个代码跟踪下
a
ayashaki

引用来自“Tengern”的评论

为什么不进行转义呐,使用“\\:\\:”。 else if ( '\\' == c ) 这段代码会进行转义处理
为什么我转义了还是报错。。 Space is not allowed after parameter prefix ':' [select @rownum\:=@rownum+1 AS rownum 用的hibernate3.3.2
李玉珏
李玉珏

引用来自“Tengern”的评论

为什么不进行转义呐,使用“\\:\\:”。 else if ( '\\' == c ) 这段代码会进行转义处理

其实在sql里,还可以用cast函数,但是都不太好,增加了开发人员的工作量,当时用双冒号,主要是用了pg的动态类型特性,到处转义的话,代码看上去不太干净
李玉珏
李玉珏

引用来自“Tengern”的评论

为什么不进行转义呐,使用“\\:\\:”。 else if ( '\\' == c ) 这段代码会进行转义处理

嗯?让开发人员写两个反斜杠?这不好吧?
好像就pg有这个双冒号的写法吧?
Tengern
Tengern
为什么不进行转义呐,使用“\\:\\:”。 else if ( '\\' == c ) 这段代码会进行转义处理
[笔记]将系统的数据库从MySQL 5.5迁移到PostgreSQL 9.1

环境 Windows Server 2003 x64 简体中文, MySQL 5.5 (UTF8编码), PostgreSQL 9.1.4-1 (UTF8编码) Spring 3.0.7, Struts 2.3.4, Hibernate 3.5.5 从MySQL迁移到PostgreSQL ------------------......

leeoo
2012/07/22
0
3
PostgreSQL数据类型-数据类型简介和布尔类型

PostgreSQL相对于其他数据库,支持数据类型很多。 PostgreSQL数据类型有布尔类型、整数类型、字符串类型、二进制字符串类型、位串类型、时间与日期类型、枚举类型、几何类型、网络地址类型、...

白豆腐徐长卿
2017/11/06
0
0
PostgreSQL和MySQL

翻译来源:https://www.2ndquadrant.com/en/postgresql/postgresql-vs-mysql/ PostgreSQL和MySQL 之间有着根本的区别。在评估两个系统之间的差异和折衷之后,必须做出明智的决定。 我们已经提...

悟道之客
05/04
0
0
PostgreSQL 数据库初体验

高强,“DBA+济南群”联合发起人。现就职于山东华鲁科技发展股份有限公司。擅长Oracle、AIX、Linux、PostgreSQL和DB2等产品的实施、运维和故障处理。曾是一名存储工程师,负责实施存储、双机...

高强
2015/10/15
0
0
PostgreSQL--数据类型格式化函数

数据类型格式化函数 主要转换方式为: 在转换过程中可以使用对结果进行限制,具体使用可见PostgreSQL 9.3.1 中文手册的章 10. 类型转换 新发现 有双冒号()这种操作,可以直接进行格式化,比如...

莫显辉
01/11
0
0
postgresql9.3.9版本部署

安装方式:源码包安装 安装环境:linux—Centos 6.5 下载Postgresql源码包 wget http://ftp.postgresql.org/pub/source/v9.3.9/postgresql-9.3.9.tar.bz2 #地址可更改,需要其他包进 http:/...

Taibai_wu
05/18
0
0
PostgreSQL 多查询条件,多个索引的选择算法与问题诊断方法

标签 PostgreSQL , 多列条件 , 多索引 , 单列索引 , 复合索引 , 联合索引 , 优化器 , 评估 , 行评估 , 成本 背景 当一个SQL中涉及多个条件,并且多个条件有多种索引可选时,数据库优化器是如...

德哥
04/18
0
0
对于SQL Server数据迁移至PostgreSQL出错的解释以及解决建议

最近对SQL Server到PostgreSQL的数据迁移时出现了问题,返回的错误为:invalid byte sequence for encoding "UTF8": 0x00。 经查证pg源代码,该问题引起的原因是sql server的字符类型字段中含...

PGSmith
2014/09/09
0
4
PostgreSQL 垃圾版本引入的索引扫描性能下降诊断

标签 PostgreSQL , 索引 , 多版本 , 垃圾版本 , pageinspect 背景 首先介绍几个背景知识,由于这些背景知识的存在,所以在某些情况下索引扫描的性能可能会出现一些问题或抖动。 导致性能下降...

德哥
04/18
0
0
数据库案例集锦 - 开发者的《如来神掌》

标签 PostgreSQL , PG DBA cookbook , PG Oracle兼容性 , PG 架构师 cookbook , PG 开发者 cookbook , PG 应用案例 背景 「剑魔独孤求败,纵横江湖三十馀载,杀尽仇寇,败尽英雄,天下更无抗...

德哥
2017/06/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java示例演示Functor 和monad

This article was initially an appendix in our Reactive Programming with RxJavabook. However introduction to monads, albeit very much related to reactive programming, didn't suit......

Quan全
16分钟前
0
0
微信官方jssdk Demo

1.html部分 <!DOCTYPE html><!-- saved from url=(0028){sh:$selfUrl} --><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="utf-8"......

koloor
20分钟前
0
0
数据库命名规范

https://www.cnblogs.com/pangguoming/p/7126512.html 摘要:当前研发工作中经常出现因数据库表、数据库表字段格式不规则而影响开发进度的问题,在后续开发使用原来数据库表时,也会因为数据...

塔塔米
20分钟前
0
0
java https 请求工具类-通用

package com.ra.common.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintW......

轻量级赤影
21分钟前
0
0
MFC界面套包BCG Pro Edition for MFC正式发布v27.3|附下载

BCGControlBar Professional Edition for MFC是MFC的一个扩展库,您可以用来构建类似于Microsoft Office 2000/XP/2003/2007/2010/2013 和 Microsoft Visual Studio-like(打印、用户定制工具......

Miss_Hello_World
21分钟前
0
0
Spring Cloud云服务 - HongHu架构common-service 项目构建过程

上一篇我们介绍了《整合spring cloud云服务架构 - HongHu云架构common-service代码结构分析》,本节我们将对common-service整个项目进行剖析,将整个构建的流程给记录下来,让更多的关注者来...

itcloud
22分钟前
0
0
Connection reset

在使用HttpClient调用后台resetful服务时,“Connection reset”是一个比较常见的问题,有同学跟我私信说被这个问题困扰很久了,今天就来分析下,希望能帮到大家。例如我们线上的网关日志就会...

夜黑人模糊灬
26分钟前
0
0
如何写PHP规范注释

所有的文档标记都是在每一行的 * 后面以@开头。如果在一段话的中间出来@的标记,这个标记将会被当做普通内容而被忽略掉。 @access 该标记用于指明关键字的存取权限:private、public或prote...

度_
26分钟前
0
0
influxDB Ppostgis

PostGis 1.需要安装postgreSQL,postgis作为插件嵌入到postgreSQL中; 2.使用zip包直接安装,需要修改 makepostgisdb_using_extensions.bat文件中的路径,用户名,密码,然后直接运行; 3.没有...

courtzjl
30分钟前
0
0
多线程Thread-多线程顺序执行

需求:现在有两个任务,任务1和任务2,任务1中有多个线程,并且任务2必须等任务1完成后才能执行。 namespace TThread{ class Program { static void Main(string[] ar...

kaixinguo314
34分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部