Spring Boot coopera con Postgresql y MybatisPlus para realizar la función de distancia común de usted de la plataforma de entrega de alimentos

Introducción

Recientemente estoy trabajando en una función comercial, y la demanda implica la necesidad de obtener la tienda física más cercana a la terminal a través del posicionamiento de la terminal. Debido a que no hay conocimiento sobre cómo calcular la distancia de las coordenadas geográficas antes, solo sé que redis puede calcular la distancia entre dos puntos de coordenadas (latitud y longitud). Pero no cubre las necesidades actuales, porque además de calcular la distancia, también necesita filtrar, ordenar y paginar. Por lo tanto, no se considera que esté implementado en redis. Es aún más imposible para la clasificación de memoria de consulta de tabla completa. Así que busqué información en Internet y encontré el complemento pgsql postgis , que es un complemento que admite el cálculo de distancia de latitud y longitud a nivel de base de datos.

Sitio web oficial de Postgis : postgis.net/

instalación postgis

En realidad, hay dos formas de instalar postgis.

La primera es instalarlo a través del generador de pila al instalar pgsql. Pero es posible que este tipo de situación no se resuelva ahora, y la vida será lenta y estancada.

Así que uso el segundo método para instalar, descargo directamente el paquete de instalación del complemento postgis desde el sitio web oficial para la instalación, y todo el proceso también es muy simple. Estoy usando pgsql 14 (postgis debe corresponder a la versión de pgsql, consulte el sitio web oficial para obtener más detalles). El proceso de instalación es más o menos los siguientes pasos:Marque Crear base de datos Seleccione el directorio de instalación de pgsql Ingrese la contraseña de la cuenta Nombre de base de datos predeterminado

Luego seleccione todos los pasos a continuación

Crear tabla de datos

-- 先创建数据库,然后执行创建插件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;

复制代码

Cree el marco de desarrollo Spring Boot + MybatisPlus

Hay algunos puntos principales a tener en cuenta al construir el código.

Agregar las dependencias correspondientes

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'
}
复制代码

agregar configuración

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. Personalice el TypeHandler para manejar el campo de ubicación geográfica de pgsql

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();
    }
}

复制代码

La conversión de tipo de procesamiento de punto de coordenadas personalizado hereda AbstractGeometryTypeHandler

@MappedTypes(Point.class)
public class PointTypeHandler extends AbstractGeometryTypeHandler<Point> {
}
复制代码

Herramienta de conversión de coordenadas

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;
        }
    }
}
复制代码

Prueba de función de interfaz

Aquí solo se realizan dos interfaces. Las coordenadas, la longitud y la latitud se pueden elegir directamente usando el mapa de Baidu o el mapa de AutoNavi.

Sistema de selección de coordenadas del mapa de Baidu

Agregar información de latitud y longitud

@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();
}
复制代码

Inserte la información de latitud y longitud + geom de la base de datos

Busque comerciantes a distancia en función de la información de ubicación

El parámetro de solicitud lleva información de longitud y latitud. La consulta a continuación es para lugares dentro de los 10,000 m de Nanhuizui.

@PostMapping("/stores")
public List<StoreResp> queryList(@RequestBody StoreReq req){
    return storeService.queryList(req);
}
复制代码
{
    "longitude": "121.979515",
    "latitude": "30.888643",
    "distance":10000
}
复制代码

mensajes devueltos

[
    {
        "id": 1,
        "name": "上海天文馆",
        "distance": 5585.5020385
    },
    {
        "id": 2,
        "name": "南汇嘴",
        "distance": 0.0
    }
]
复制代码

El sql de la consulta de la base de datos es en realidad:

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;
复制代码

Dirección de la fuente

github.com/Grt1228/pos…

Referencias:

[1] Sistema de recogida de coordenadas del mapa de Baidu: api.map.baidu.com/lbsapi/getp…

[2] Consulte el artículo csdn: blog.csdn.net/zxt521yt/ar…

Supongo que te gusta

Origin juejin.im/post/7083293713480286222
Recomendado
Clasificación