SpringBoot2.3+MybatisPlus3.3.1+PostgresSQL11+net.postgis.postgis-jdbc2.5.0整合地图经纬度Geometry类型

万开畅
2023-12-01

1、修改数据库字段类型为geometry

ALTER TABLE t_test
	ALTER COLUMN lnglat_geom TYPE geometry(Point,4326);

2、添加postgis依赖

<!-- postgis -->
<dependency>
    <groupId>net.postgis</groupId>
    <artifactId>postgis-jdbc</artifactId>
    <version>2.5.0</version>
</dependency>

3、自定义抽象TypeHandler,子类可以是点,线,多点,多边形,看自己使用场景用哪个都行。

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.postgis.Geometry;
import org.postgis.PGgeometry;

/**
 * @author kevin
 *
 */
public abstract class AbstractGeometryTypeHandler<T extends Geometry> extends BaseTypeHandler<T> {
	public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        PGgeometry geometry = new PGgeometry();
        geometry.setGeometry(parameter);
        ps.setObject(i, geometry);
        
    }
 
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        PGgeometry pGgeometry = (PGgeometry) rs.getObject(columnName);
        if (pGgeometry == null) {
            return null;
        }
        return (T) pGgeometry.getGeometry();
    }
 
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        PGgeometry pGgeometry = (PGgeometry) rs.getObject(columnIndex);
        if (pGgeometry == null) {
            return null;
        }
        return (T) pGgeometry.getGeometry();
    }
 
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        PGgeometry pGgeometry = (PGgeometry) cs.getObject(columnIndex);
        if (pGgeometry == null) {
            return null;
        }
        return (T) pGgeometry.getGeometry();
    }
}

4、定义“坐标点”子类,继承上面的抽象类

import org.apache.ibatis.type.MappedTypes;
import org.postgis.Point;

/**
 * 点,子类
 * @author kevin
 *
 */

@MappedTypes(Point.class)
public class PointTypeHandler extends AbstractGeometryTypeHandler<Point> {

}

5、定义“多坐标点”子类,继承上面的抽象类

import org.apache.ibatis.type.MappedTypes;
import org.postgis.MultiPoint;

/**
 * 多点,子类
 * @author kevin
 *
 */

@MappedTypes(MultiPoint.class)
public class MultiPointTypeHandler extends AbstractGeometryTypeHandler<MultiPoint> {

}

6、定义“线”子类,继承上面的抽象类

import org.apache.ibatis.type.MappedTypes;
import org.postgis.LineString;

/**
 * 线,子类
 * @author kevin
 *
 */
@MappedTypes(LineString.class)
public class LineStringTypeHandler extends AbstractGeometryTypeHandler<LineString> {

}

7、定义“多边形”子类,继承上面的抽象类

import org.apache.ibatis.type.MappedTypes;
import org.postgis.Polygon;

/**
 * 多边形,子类
 * @author kevin
 *
 */

@MappedTypes(Polygon.class)
public class PolygonTypeHandler extends AbstractGeometryTypeHandler<Polygon> {

}

8、定义坐标点格式化工具类

import org.apache.commons.lang3.ArrayUtils;
import org.postgis.LineString;
import org.postgis.LinearRing;
import org.postgis.Point;
import org.postgis.Polygon;

/**
 * 坐标点格式化工具类
 */
public class CorrdinateUtil {
    /**
     * 格式化Polygon类型:
     * 将Vertexts字符串转换成Polygon类型
     * @param vertexes 多边形围栏形状点(顺时针或逆时针):   "double,double; double,double; ...;double,double"
     * @return Polygon
     */
    public static Polygon formatPolygon(String vertexes) throws Exception{
        vertexes = CorrdinateUtil.stringUtils(vertexes);
        String[] points = vertexes.split(";");
        int length = points.length;
        Point[] pointArray = new Point[length + 1];
        for (int i = 0;i<length;i++){
            String[] xy = points[i].split(",");
            pointArray[i] = new Point(Double.parseDouble(xy[0]),Double.parseDouble(xy[1]));
        }
        //首尾两点一致,封闭形成多边形
        String[] firstPoint = points[0].split(",");
        pointArray[length] = new Point(Double.parseDouble(firstPoint[0]),Double.parseDouble(firstPoint[1]));
        LinearRing linearRing = new LinearRing(pointArray);
        Polygon polygon = new Polygon(new LinearRing[]{linearRing});
        return polygon;
    }
 
    /**
     * 格式化Point类型:
     * 将Vertexts字符串转换成Point类型
     * @param vertexes 点坐标:"double,double"
     * @return Point
     */
    public static Point formatPoint(String vertexes) throws Exception{
        vertexes = CorrdinateUtil.stringUtils(vertexes);
        String[] split = vertexes.split(",");
        Point point = new Point(Double.parseDouble(split[0]), Double.parseDouble(split[1]));
        point.dimension = 2;
        //WGS84坐标系,也就是GPS使用的坐标
        point.srid = 4326;
        return point;
    }
 
    /**
     * 经纬度转为Point对象
     * 
     * @param lnglat
     * @return
     */
    public static Point lnglatToPoint(Double[] lnglat) {
    	if(ArrayUtils.isNotEmpty(lnglat)) {
    		String vertexes = String.valueOf(lnglat[0])+","+String.valueOf(lnglat[1]);
    		try {
    			return CorrdinateUtil.formatPoint(vertexes);
    		} catch (Exception e) {
    			
    		}
    	}
    	return null;
	}
    
    /**
     * 格式化LineString类型:
     * 将Vertexts字符串转换成LineString类型
     * @param vertexes 折线点:   "double,double; double,double; ...;double,double"
     * @return LineString
     */
    public static LineString formatLineString(String vertexes) throws Exception{
        vertexes = CorrdinateUtil.stringUtils(vertexes);
        String[] points = vertexes.split(";");
        int length = points.length;
        Point[] pointArray = new Point[length];
        for (int i = 0;i<length;i++){
            String[] xys = points[i].split(",");
            pointArray[i] = new Point(Double.parseDouble(xys[0]),Double.parseDouble(xys[1]));
        }
        LineString lineString = new LineString(pointArray);
        return lineString;
    }
 
    //过滤""号
    public static String stringUtils(String str){
        return str.replace("\"","");
    }
}

9、定义数据库实体PO对象

import java.io.Serializable;

import org.postgis.Point;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;

//此处改为自己的TypeHandler包路径
import *.*.*.*.ArrayTypeHandler;
import *.*.*.*.PointTypeHandler;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

/**
 * Entity
 *
 * @author kevin
 */
@Data
@TableName(autoResultMap = true)
public class Test implements Serializable{
    private static final long serialVersionUID = 1L;
    /**
     * id
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 经纬度
     */
    @TableField(value = "lnglat", typeHandler = ArrayTypeHandler.class)
    private Double[] lnglat;

    /**
     * 地图聚合点
     */
    @TableField(value = "lnglat_geom", typeHandler = PointTypeHandler.class)
    private Point lnglatGeom;

    /**
     * 位置
     */
    @TableField("location")
    private String location;

    /**
     * 是否删除
     */
    @TableField(value = "is_deleted", fill = FieldFill.INSERT)
    @TableLogic //逻辑删除
    private Integer isDeleted;
    
    /**
     * 版本变更号 
     */
    @Version //乐观锁
    @TableField("revision")
    private Integer revision;
    
}

10、使用

//地图经纬度
Double[] lnglat = new Double[];
lnglat[0] = 104.345666;
lnglat[1] = 39.99999;

Test entity = new Test();
//用工具类转换为地图坐标点
entity.setLnglatGeom(CorrdinateUtil.lnglatToPoint(lnglat));

//调用mybatisplus的保存
this.baseMapper.insert(entiry);
 类似资料: