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

在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 );
                }
            }
        }
    }
时间: 2024-08-29 17:28:12

解决Hibernate不支持PostgreSQL中双冒号(::)的Bug的相关文章

php中双冒号::的用法

注:本篇博客系转载,出处不可考(至少对我来说不可考...) 双冒号操作符即作用域限定操作符Scope Resolution Operator可以访问静态.const和类中重写的属性与方法. 在类定义外使用的话,使用类名调用.在PHP 5.3.0,可以使用变量代替类名. Program List:用变量在类定义外部访问 <?php class Fruit { const CONST_VALUE = 'Fruit Color'; } $classname = 'Fruit'; echo $class

css中双冒号和单冒号区别

:——是指的伪类 ::——是指的伪元素 1.字面意思: 伪类,1.css中有类选择器,某些元素并未定义类名,就可以通过伪类赋予样式,如:[:nth-child(n)]:2.伪类可以应用于元素执行某种状态,如:[:hover]鼠标经过元素时 伪元素,创建一个新元素应用于文档,但是并不存在于文档中. 常见的伪元素选择器:  ::first-letter 选择元素文本的第一个字(母).  ::first-line 选择元素文本的第一行.  ::before 在元素内容的最前面添加新内容.  ::aft

numpy中双冒号的作用

1 import numpy as np 2 a = np.array([[1, 2, 3, 1, 3, 5], [4, 5, 6, 2, 4, 3]]) 3 print('a') 4 print(a) 5 print(a[:, 0::2]) 6 7 # a 8 # [[1 2 3 1 3 5] 9 # [4 5 6 2 4 3]] 10 # [[1 3 3] 11 # [4 6 4]] 12 13 b = np.array([[1, 2, 3, 1, 3, 5], [4, 5, 6, 2, 4

解决IE6不支持position:fixed固定定位的bug(转载范鸭)

http://blog.funya.in/csscss3/ie6-fixed-bug/ 在IE6中实现 position:fixed; 的办法: 浏览器头部固定 .fixed_top { position:fixed; top:0px; } * html .fixed_top /* IE6 头部固定 */{ position:absolute; bottom:auto; top:expression(eval(document.documentElement.scrollTop)); } 浏览器

转载——c++中冒号(:)和双冒号(::)的用法

1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) typedef struct _XXX{ unsigned char a:4; unsigned char c; } ; XXX (2)构造函数后面的冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型. struct _XXX{ _XXX() : y(0xc0) {} }; (3) public:和private:后面的冒号,表示后面定义的所有成员都是公有或私有的,直到下一个"pub

C++中的双冒号作用

1. 作用域符号::的前面一般是类名称,后面一般是该类的成员名称,C++为例避免不同的类有名称相同的成员而采用作用域的方式进行区分 如:A,B表示两个类,在A,B中都有成员member.那么 A::member就表示类A中的成员member B::member就表示类B中的成员member 2. 全局作用域符号: 例如: #include <stdio.h> int count = 0; //全局变量 0 void main() { int count = 10; //局部变量10 print

在Myeclipse中移除项目对Hibernate的支持

在Myeclipse中移除项目对Hibernate的支持 在使用Hibernate框架进行开发时可能会遇到配置错误或者需要删除Hibernate支持的情况.下面就说一下如何彻底移除项目的Hibernate支持.移除后就能重新添加Hibernate支持,重新配置了. 1.找到你的项目的目录 2.删除.myhibernatedata文件 3.找到.project文件,用记事本打开,找到如下字段 <buildCommand>   <name>com.genuitec.eclipse.hi

c++中冒号(:)和双冒号(::)的用法

1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) typedef struct _XXX{ unsigned char a:4; unsigned char c; } ; XXX (2)构造函数后面的冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型. struct _XXX{ _XXX() : y(0xc0) {} }; (3) public:和private:后面的冒号,表示后面定义的所有成员都是公有或私有的,直到下一个"pub

解决hibernate中的懒加载(延迟加载)问题

解决hibernate中的懒加载(延迟加载)问题 我们在开发的时候经常会遇到延迟加载问题,在实体映射时,多对一和多对多中,多的一样的属性默认是lazy="true"(即,默认是延迟加载), 如:<many-to-one name="parent" class="Department" column="parentId" lazy="true"/> 延迟加载表现在:比如:我们要查询id为2的部门数