Einführung
Vor kurzem arbeite ich an einer Geschäftsfunktion, und die Anforderung beinhaltet die Notwendigkeit, durch die Positionierung des Terminals das physische Geschäft zu erhalten, das dem Terminal am nächsten liegt. Da es vorher keine Kenntnisse über die Berechnung der Entfernung von geografischen Koordinaten gibt, weiß ich nur, dass redis die Entfernung zwischen zwei Koordinatenpunkten (Breitengrad und Längengrad) berechnen kann. Aber es entspricht nicht den aktuellen Anforderungen, denn es muss neben der Berechnung der Entfernung auch filtern, sortieren und paginieren. Daher wird es nicht als in Redis implementiert angesehen. Es ist sogar noch unmöglicher für das Sortieren des vollständigen Tabellenabfragespeichers. Also habe ich im Internet nach Informationen gesucht und das pgsql-Plug-in postgis gefunden , ein Plug-in, das die Berechnung von Breiten- und Längengraden auf Datenbankebene unterstützt.
Offizielle Postgis- Website: postgis.net/
Postgis-Installation
Es gibt tatsächlich zwei Möglichkeiten, Postgis zu installieren.
Die erste besteht darin, es bei der Installation von pgsql über den Stack Builder zu installieren. Aber diese Art von Situation kann jetzt nicht eintreten, und das Leben wird langsam und festgefahren sein.
Also verwende ich die zweite Methode zur Installation, lade das Postgis-Plug-in-Installationspaket direkt von der offiziellen Website zur Installation herunter, und der gesamte Vorgang ist auch sehr einfach. Ich verwende pgsql 14 (postgis muss der pgsql-Version entsprechen, siehe die offizielle Website für Details). Der Installationsprozess besteht grob aus den folgenden Schritten:
Wählen Sie dann alle Schritte unten aus
Datentabelle erstellen
-- 先创建数据库,然后执行创建插件postgis
CREATE EXTENSION postgis;
create table t_store
(
id serial not null
constraint t_store_pk
primary key,
name varchar(64) not null,
longitude varchar,
latitude varchar not null,
geom geometry(Point, 4326) not null,
create_time timestamp default now() not null,
update_time timestamp default now() not null
);
comment on column t_store.name is '名称';
comment on column t_store.longitude is '经度';
comment on column t_store.latitude is '纬度';
comment on column t_store.geom is '地理位置信息';
alter table t_store
owner to postgres;
复制代码
Erstellen Sie Spring Boot + MybatisPlus-Entwicklungsframework
Beim Erstellen des Codes sind einige wichtige Punkte zu beachten.
Fügen Sie entsprechende Abhängigkeiten hinzu
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compile group: 'com.baomidou', name: 'mybatis-plus-boot-starter', version: '3.5.1'
// postgis 插件依赖包
compile group: 'net.postgis', name: 'postgis-jdbc', version: '2.5.1'
compile group: 'org.postgresql', name: 'postgresql'
}
复制代码
Konfiguration hinzufügen
spring.application.name=gradle_test
server.port=8080
# pgsql
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/postgis_test
spring.datasource.username=postgres
spring.datasource.password=123456
# mybatis config :自定义的类型转换类
mybatis-plus.type-handlers-package=com.unfbx.gradle_test.config.typehandler
复制代码
2. Passen Sie den TypeHandler an, um das geografische Standortfeld von pgsql zu verarbeiten
package com.unfbx.gradle_test.config.typehandler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.postgis.Geometry;
import org.postgis.PGgeometry;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 描述:
*
* @author
* @date 2022-04-03
*/
public class AbstractGeometryTypeHandler<T extends Geometry> extends BaseTypeHandler<T> {
/**
* 表示向PreparedStatement里面设置值
*
* @param ps
* @param i
* @param parameter
* @param jdbcType
* @throws SQLException
*/
public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
PGgeometry geometry = new PGgeometry();
geometry.setGeometry(parameter);
ps.setObject(i, geometry);
}
/**
* 根据列名获取值
*
* @param rs
* @param columnName
* @return
* @throws SQLException
*/
public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
PGgeometry pGgeometry = (PGgeometry) rs.getObject(columnName);
if (pGgeometry == null) {
return null;
}
return (T) pGgeometry.getGeometry();
}
/**
* 根据列索引位置获取值
*
* @param rs
* @param columnIndex
* @return
* @throws SQLException
*/
public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
PGgeometry pGgeometry = (PGgeometry) rs.getObject(columnIndex);
if (pGgeometry == null) {
return null;
}
return (T) pGgeometry.getGeometry();
}
/**
* 获取值 通过列索引
*
* @param cs
* @param columnIndex
* @return
* @throws SQLException
*/
public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
PGgeometry pGgeometry = (PGgeometry) cs.getObject(columnIndex);
if (pGgeometry == null) {
return null;
}
return (T) pGgeometry.getGeometry();
}
}
复制代码
Die Konvertierung des benutzerdefinierten Koordinatenpunktverarbeitungstyps erbt AbstractGeometryTypeHandler
@MappedTypes(Point.class)
public class PointTypeHandler extends AbstractGeometryTypeHandler<Point> {
}
复制代码
Werkzeug zur Koordinatenkonvertierung
public class CoordinatesUtil {
public static Point buildPoint(String longitude, String latitude) throws Exception {
if (StringUtils.isEmpty(longitude) || StringUtils.isEmpty(latitude)) {
throw new Exception("坐标数据异常");
}
try {
Point point = new Point(Double.parseDouble(longitude),Double.parseDouble(latitude));
return point;
} catch (Exception e) {
throw e;
}
}
}
复制代码
Schnittstellenfunktionstest
Hier werden nur zwei Schnittstellen hergestellt. Die Koordinaten, Längen- und Breitengrade können direkt mit der Baidu-Karte oder der AutoNavi-Karte ausgewählt werden.
Baidu-Kartenkoordinaten-Auswahlsystem
Fügen Sie Breiten- und Längeninformationen hinzu
@PostMapping("/store")
public String add(@RequestBody Store store) throws Exception {
store.setGeom(CoordinatesUtil.buildPoint(store.getLongitude(), store.getLatitude()));
storeService.save(store);
return "添加成功,id:" + store.getId();
}
复制代码
Suchen Sie anhand von Standortinformationen nach Händlern in der Nähe
Der Anforderungsparameter enthält Längen- und Breitengradinformationen. Die folgende Abfrage gilt für Orte innerhalb von 10.000 m von Nanhuizui.
@PostMapping("/stores")
public List<StoreResp> queryList(@RequestBody StoreReq req){
return storeService.queryList(req);
}
复制代码
{
"longitude": "121.979515",
"latitude": "30.888643",
"distance":10000
}
复制代码
zurückgegebene Nachrichten
[
{
"id": 1,
"name": "上海天文馆",
"distance": 5585.5020385
},
{
"id": 2,
"name": "南汇嘴",
"distance": 0.0
}
]
复制代码
Die SQL der Datenbankabfrage lautet eigentlich:
select
id, name,geom,
ST_Distance(ST_GeographyFromText(ST_AsText('POINT(121.926753 30.912628)')),
ST_GeographyFromText(ST_AsText(geom))) as distance
from
t_store;
复制代码
Quelladresse
Verweise:
[1] Baidu-Kartenkoordinatenaufnahmesystem: api.map.baidu.com/lbsapi/getp…
[2] Siehe csdn-Artikel: blog.csdn.net/zxt521yt/ar…