要生成的sql:
作用是利用postgreGIS數據庫函數計算兩點(經緯度已知)的距離。
SELECT ST_Distance(
ST_Transform(ST_GeomFromText('POINT(-87.734087560562 43.770129071141)',4326),26986),
ST_Transform(ST_GeomFromText('POINT(-87.747382933006 43.759234252055)', 4326),26986)
);
最后成功的寫法:
<select id="selectDistance" resultType="java.lang.String" parameterType="java.util.Map">
SELECT ST_Distance(
<if test="lot_lat != null" >
ST_Transform(ST_GeomFromText(<![CDATA['POINT(${lot_lat})']]> ,4326),26986),
</if>
<if test="parkingPointStr != null">
ST_Transform(ST_GeomFromText(<![CDATA['${parkingPointStr}']]>, 4326),26986))
</if>
</select>
${lot_lat}是字符串:-87.734087560562 43.770129071141
${parkingPointStr}是字符串POINT(-87.747382933006 43.759234252055)
注意1:單引號的轉義
方式a:如上使用<![CDATA[……]]>
方式b:使用xml的轉義字符:
<select id="selectDistance" resultType="java.lang.String" parameterType="java.util.Map">
SELECT ST_Distance(
<if test="lot_lat != null" >
ST_Transform(ST_GeomFromText(' POINT(${lot_lat}) ',4326),26986),
</if>
<if test="parkingPointStr != null">
ST_Transform(ST_GeomFromText('${parkingPointStr} ', 4326),26986))
</if>
</select>
方式c:concat拼接的方式。
剛開始想拼接一對單引號出來,不行:
<select id="selectDistance" resultType="java.lang.String" parameterType="java.util.Map">
SELECT ST_Distance(
<if test="lot_lat != null" >
ST_Transform(ST_GeomFromText(concat(E'\'','POINT(${lot_lat})',E'\'','),4326),26986),
</if>
<if test="parkingPointStr != null">
ST_Transform(ST_GeomFromText(concat(E'\'','${parkingPointStr}',E'\'','), 4326),26986))
</if>
</select>
后來堅持不懈,發現是這么寫:
<select id="selectDistance" resultType="java.lang.String" parameterType="java.util.Map">
SELECT ST_Distance(
<if test="lot_lat != null" >
ST_Transform(ST_GeomFromText(concat('POINT(${lot_lat})'),4326),26986),
</if>
<if test="parkingPointStr != null">
ST_Transform(ST_GeomFromText(concat('${parkingPointStr}'), 4326),26986))
</if>
</select>
這樣也行:
<select id="selectDistance" resultType="java.lang.String" parameterType="java.util.Map">
SELECT ST_Distance(
<if test="lot_lat != null" >
ST_Transform(ST_GeomFromText(concat('POINT(',#{lot_lat},')'),4326),26986),
</if>
<if test="parkingPointStr != null">
ST_Transform(ST_GeomFromText(concat('${parkingPointStr}'), 4326),26986))
</if>
</select>
這樣也行:
<select id="selectDistance" resultType="java.lang.String" parameterType="java.util.Map">
SELECT ST_Distance(
<if test="lot_lat != null" >
ST_Transform(ST_GeomFromText(concat('POINT(',#{lot_lat},')'),4326),26986),
</if>
<if test="parkingPointStr != null">
ST_Transform(ST_GeomFromText(concat(#{parkingPointStr}), 4326),26986))
</if>
</select>
concat函數解析后會自帶單引號?我之前為了加上單引號還這么寫呢:SELECT concat('''','POINT(116.289573 39.892352)','''')
SELECT concat('''','POINT(116.289573 39.892352)','''')
SELECT concat('POINT(-87.747382933006 43.759234252055)')
SELECT '''' || 'POINT(-87.747382933006 43.759234252055)' || ''''
這樣不行:
<select id="selectDistance" resultType="java.lang.String" parameterType="java.util.Map">
SELECT ST_Distance(
<if test="lot_lat != null" >
ST_Transform(ST_GeomFromText('\''POINT(${lot_lat}) '\'',4326),26986),
</if>
<if test="parkingPointStr != null">
ST_Transform(ST_GeomFromText('\''${parkingPointStr} '\'', 4326),26986))
</if>
</select>
sqlSELECT concat('\'','ddd','\'') from t_parking
也有語法錯誤,應該寫為SELECT concat(E'\'','ddd',E'\'') from t_parking
,postgresql轉義放在E'\要轉義的內容'
里。詳見
折騰半天,發現這樣寫,最簡單
String param = "POINT(" + longitude + " " + latitude + ")";
ST_GeomFromText(#{param},4326)
注意2:單引號為什么不能用雙引號取代
sql里單引號不能被雙引號取代着用。
注意3:${} 與 #{}的區別
前者是直接把字面值加在sql里,完全是字符串替換,當作占位符。常常用來傳遞表名,字段名,如order by ${param}
mybatis在處理#{}時,會將sql中的#{}替換為?號,調用PreparedStatement的set方法來賦值,有預編譯的機制。另外,傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。
后注入的參數將不會再進行SQL編譯。我們知道,SQL注入是發生在編譯的過程中,因為惡意注入了某些特殊字符,最后被編譯成了惡意的執行操作。而預編譯機制則可以很好的防止SQL注入。
注意4:mybatis里寫的一條sql里可以${} 與 #{}混着用嗎?
比如這條語句:
SELECT ST_Distance(ST_Transform(ST_GeomFromText('POINT(117.343454 40.8978999)',4326),26986),ST_Transform(ST_GeomFromText('POINT(116.289573 39.892352)', 4326),26986))
FROM t_parking
WHERE id='0652b36f115c42578d13ffa45c4589c8'
寫成:
<select id="selectDistance" resultType="java.lang.String" parameterType="java.util.Map">
SELECT ST_Distance(
<if test="lot_lat != null" >
ST_Transform(ST_GeomFromText(<![CDATA['POINT(${lot_lat})']]> ,4326),26986),
</if>
<if test="parkingPointStr != null">
ST_Transform(ST_GeomFromText(<![CDATA['${parkingPointStr}']]>, 4326),26986))
</if>
</select>
FROM t_parking
<where>
<if test="id != null and id != ''">
and id = #{id,jdbcType=VARCHAR}
</if>
</where>
可以嗎?
當然是可以的,但${}里不能帶,jdbcType=VARCHAR
寫這樣and id = ${id,jdbcType=VARCHAR}
報錯:org.postgresql.util.PSQLException: 錯誤: 語法錯誤 在輸入的末尾\n 位置
。
寫這樣and id = '${id,jdbcType=VARCHAR}'
報錯:內部錯誤。
寫這樣and id = '${id}'
當然是正確的。
寫這樣and id = ${id}
當然是有語法錯誤的。
另附postgis相關資料:
https://blog.csdn.net/qq_36588972/article/details/78902195
https://blog.csdn.net/zcc0618/article/details/72972188
https://blog.csdn.net/qq_36017609/article/details/85730172
https://www.cnblogs.com/kaituorensheng/p/4647901.html
CREATE database testgis;--新建一個庫
CREATE EXTENSION postgis;--給該庫啟用PostGIS(包括柵格),出現表spatial_ref_sys
CREATE EXTENSION postgis_topology;--啟用拓撲topology庫
select ST_GeomFromText('POINT(116.289573 39.892352)', 4326); --試用
st_astext(inf_comp_components_point.geom) --得到POINT(116.289573 39.892352)
字符串
給表t_parking添加一個地理屬性字段geom,坐標系是4326(epsg4326,經緯度),2維
SELECT AddGeometryColumn ('t_parking', 'geom', 4326, 'POINT', 2)
update t_parking geom set geom = ST_GeomFromText('POINT(116.289573 39.892352)', 4326) where id='0652b36f115c42578d13ffa45c4589c8'
SELECT ST_ASTEXT(geom) geom FROM t_parking where id='0652b36f115c42578d13ffa45c4589c8'
select a1.attname as column_name,t.typname as data_type,d.description as column_comment
from (select a.attname,a.attrelid,a.atttypid,a.attnum from pg_attribute a,pg_class c where c.relname = 't_parking' and a.attnum>0 and a.attrelid=c.oid)a1 left join pg_type t on a1.atttypid=t.oid left join pg_description d on d.objoid=a1.attrelid and d.objsubid=a1.attnum;