最近使用postgis的地理函数做一些区域查询判断,SQL代码如下:


        
            
                AND ST_Intersects ( ST_Buffer (ST_GeomFromText ('POINT(${geog.centerString})', ${geog.srid}) ::
                geography, ${geog.radiusMetre} ) :: geography, position )
            
            
                and ST_Intersects(ST_GeomFromText('POLYGON((${geog.pointArr}))',
                ${geog.srid})::geography,
                position )
            
            
                and ST_Intersects(ST_GeomFromText('POLYGON((${geog.pointArr}))',
                ${geog.srid})::geography,
                position )
            
        
    

执行时报错:

bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: function st_geomfromtext(unknown, integer) does not exist
  建议:No function matches the given name and argument types. You might need to add explicit type casts.

查看PostgrelSQL的官方手册(ST_GeogFromText)关于函数的解释如下:

Postgis 地理函数使用_第1张图片

初步怀疑是mybatis参数传递导致,将'POINT()'部分整个作为参数传递,修改后SQL如下:

AND ST_Intersects ( ST_Buffer (ST_GeomFromText (${geog.centerString}, ${geog.srid}) :: geography, ${geog.radiusMetre} ) :: geography, position )

执行继续报错:

bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: function st_geomfromtext(variable char, integer) does not exist
  建议:No function matches the given name and argument types. You might need to add explicit type casts.

进一步排查:
将navicat客户可执行的sql写死代码里测试:

select ST_GeomFromText('POINT(123.480833 35.643900)',4326);

依旧是上面的错误, 时间已经过去2小时...

此时,曾经用hibernate实现postgis函数查询的同事过来指点江山,于是开始找各种mybatis转换驱动, 尝试各种自定义TypeHandler,时间又过去了1小时...

为了避免hibernate和mybatis优劣的讨论,尝试直接用jdbcTemplate调用函数,依旧是同样的错误。

检查postgrelSQL驱动版本,直到想到schema。

当前项目是一库下多schema,jdbc连接时,指定了currentSchema=xxx,但是这个schema不是public,也没有设置searchPath,所以无法正确执行public的function。将函数统一加上public.前缀,sql执行通过!

进一步优化,怎么用searchPath,有一篇参考文章介绍的挺好(PostgreSQL模式),奈何尝试了几次设置,都未成功,后经公司DBA架构师指点,直接在jdbcurl上,设置currentSchema=xxx,public, 即优雅的解决此问题。