天天看點

從零開始,建構電子地圖網站:0_8_mybatis+TypeHandler+jts處理geometry一、引入依賴二、增加mybatis自定義類三、修改model四、修改dao五、修改mapper六、修改service七、修改controller八、啟動測試九、送出git,從git上pull分支

接上文,我們的資料裡是有幾何類型的,點和面。

我們在navicat中運作一條sql:SELECT geom FROM v6_time_cnty_pts_utf_wgs84 LIMIT 1

查出的結果geom是0101000020E6100000A165DD3F16C55B4089963C9E96814340

這種格式是geohash編碼的。

再運作另一條sql:SELECT st_astext(geom) FROM v6_time_cnty_pts_utf_wgs84 LIMIT 1

POINT(111.079483 39.012409)

這種是WKT格式。

都是空間資料的存儲格式,WKT比geohash編碼要直覺。

在mybatis中,直接查geometry對象,傳回的是字元類型的geohash,但是互動的時候,我們不能返一串geohash碼。對于後端來說,我們應該直接操作geometry類,給前端提供json數組。

還用之前的程式,看看怎麼對geometry對象進行增删改查。

Springboot2+mybatis+postgresql+typehandler+jts;

一、引入依賴

Jts是空間處理jar包,功能很全很強大,這個jar包的maven依賴,我們之前已經在pom中引用了。

再加一個解析json的jar包。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.1.6.RELEASE</version>

        <relativePath/> <!-- lookup parent from repository -->

    </parent>

    <groupId>com.history</groupId>

    <artifactId>gismap</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <name>gismap</name>

    <description>Demo project for Spring Boot</description>



    <properties>

<!--        标注一下編碼為utf8,jdk版本為1.8-->

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <java.version>1.8</java.version>

    </properties>



    <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-jdbc</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-thymeleaf</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

        <dependency>

            <groupId>org.mybatis.spring.boot</groupId>

            <artifactId>mybatis-spring-boot-starter</artifactId>

            <version>2.1.0</version>

        </dependency>



        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-devtools</artifactId>

            <scope>runtime</scope>

            <optional>true</optional>

        </dependency>

        <dependency>

            <groupId>org.postgresql</groupId>

            <artifactId>postgresql</artifactId>

            <version>42.2.2</version>

            <!--         <scope>runtime</scope>-->

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-configuration-processor</artifactId>

            <optional>true</optional>

        </dependency>

        <dependency>

            <groupId>org.projectlombok</groupId>

            <artifactId>lombok</artifactId>

            <version>1.18.8</version>

            <optional>true</optional>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>



        <dependency>

            <groupId>org.apache.commons</groupId>

            <artifactId>commons-lang3</artifactId>

            <version>3.4</version>

        </dependency>



        <!--解析json的-->

        <dependency>

            <groupId>com.fasterxml.jackson.core</groupId>

            <artifactId>jackson-core</artifactId>

        </dependency>

        <dependency>

            <groupId>com.fasterxml.jackson.core</groupId>

            <artifactId>jackson-databind</artifactId>

        </dependency>

        <dependency>

            <groupId>com.fasterxml.jackson.datatype</groupId>

            <artifactId>jackson-datatype-joda</artifactId>

        </dependency>

        <dependency>

            <groupId>com.fasterxml.jackson.module</groupId>

            <artifactId>jackson-module-parameter-names</artifactId>

        </dependency>

        <!-- 分頁插件 -->

        <dependency>

            <groupId>com.github.pagehelper</groupId>

            <artifactId>pagehelper-spring-boot-starter</artifactId>

            <version>1.2.5</version>

        </dependency>

        <!-- alibaba的druid資料庫連接配接池 -->

        <dependency>

            <groupId>com.alibaba</groupId>

            <artifactId>druid-spring-boot-starter</artifactId>

            <version>1.1.9</version>

        </dependency>

        <!-- 解析幾何geometry對象用的-->

        <dependency>

            <groupId>com.vividsolutions</groupId>

            <artifactId>jts</artifactId>

            <version>1.13</version>

        </dependency>

        <!--引入alibaba的json處理jar包-->

        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->

        <dependency>

            <groupId>com.alibaba</groupId>

            <artifactId>fastjson</artifactId>

            <version>1.2.47</version>

        </dependency>



    </dependencies>



    <build>

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>

        </plugins>

    </build>



</project>      

二、增加mybatis自定義類

建立一個包:D:\gismap\java\gismap\src\main\java\com\history\gismap\mybatis

在這個package包下建立一個類,D:\gismap\java\gismap\src\main\java\com\history\gismap\mybatis\GeometryTypeHandler.java,擴充mybatis的typehandler,WKBReader.hexToBytes(pGgeometry.getValue())就是從解碼geohash,擷取geometry類。

package com.history.gismap.mybatis;



import com.vividsolutions.jts.geom.Geometry;

import com.vividsolutions.jts.io.ParseException;

import com.vividsolutions.jts.io.WKBReader;

import org.apache.ibatis.type.BaseTypeHandler;

import org.apache.ibatis.type.JdbcType;

import org.apache.ibatis.type.MappedTypes;

import org.postgresql.util.PGobject;



import java.sql.CallableStatement;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

@MappedTypes(Geometry.class)

public class GeometryTypeHandler  extends BaseTypeHandler<Geometry> {



    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Geometry geometry, JdbcType jdbcType) throws SQLException {

        PGobject pGobject=new PGobject();

        pGobject.setValue(geometry.toString());

        pGobject.setType("geometry");

        preparedStatement.setObject(i,pGobject);

    }



    public Geometry getNullableResult(ResultSet resultSet, String columnName) throws SQLException {

        PGobject pGgeometry= (PGobject) resultSet.getObject(columnName);

        if(pGgeometry==null){

            return null;

        }else{

            WKBReader wkbReader=new WKBReader();

            try {

                return wkbReader.read(WKBReader.hexToBytes(pGgeometry.getValue()));

            } catch (ParseException e) {

                e.printStackTrace();

                return null;

            }

        }

    }



    public Geometry getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {

        PGobject pGgeometry= (PGobject) resultSet.getObject(columnIndex);

        if(pGgeometry==null){

            return null;

        }else{

            WKBReader wkbReader=new WKBReader();

            try {

                return wkbReader.read(WKBReader.hexToBytes(pGgeometry.getValue()));

            } catch (ParseException e) {

                e.printStackTrace();

                return null;

            }

        }

    }



    public Geometry  getNullableResult(CallableStatement callableStatement, int i) throws SQLException {

        PGobject pGgeometry= (PGobject) callableStatement.getObject(i);

        if(pGgeometry==null){

            return null;

        }else{

            WKBReader wkbReader=new WKBReader();

            try {

                return wkbReader.read(WKBReader.hexToBytes(pGgeometry.getValue()));

            } catch (ParseException e) {

                e.printStackTrace();

                return null;

            }

        }

    }



}      

三、修改model

加一個geometry屬性。

D:\gismap\java\gismap\src\main\java\com\history\gismap\model\PointModel.java

package com.history.gismap.model;



import com.vividsolutions.jts.geom.Geometry;

import lombok.Getter;

import lombok.Setter;

import lombok.ToString;



@Getter

@Setter

@ToString

public class PointModel {

    private Integer gId;

    private String nameCh;

    private Geometry geometry;



}      

四、修改dao

這個檔案沒啥要改的。

D:\gismap\java\gismap\src\main\java\com\history\gismap\dao\MapDao.java

package com.history.gismap.dao;



import com.history.gismap.model.PointModel;

import org.apache.ibatis.annotations.Param;

import org.springframework.stereotype.Service;

import java.util.List;



@Service

public interface MapDao {

    List<PointModel> getCntyPoint(@Param("gId") Integer gId);

    int insertCntyPoint(PointModel pointModel);

    int updateCntyPoint(PointModel pointModel);

    int deleteCntyPoint(@Param("gId") Integer gId);

}      

五、修改mapper

主要是加上typeHandler="com.history.gismap.mybatis.GeometryTypeHandler"

D:\gismap\java\gismap\src\main\resources\mapper\HistoryGISMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="com.history.gismap.dao.MapDao" >

    <resultMap id="pointModelResult" type="com.history.gismap.model.PointModel">

        <result property="gId" column="gid" jdbcType="BIGINT"/>

        <result property="nameCh" column="name_ch" jdbcType="VARCHAR"/>

        <result property="geometry" column="geom" typeHandler="com.history.gismap.mybatis.GeometryTypeHandler"/>

    </resultMap>

    <sql id="BASE_TABLE">

    v6_time_cnty_pts_utf_wgs84

  </sql>

    <sql id="BASE_COLUMN">

    gid,name_ch,geom

  </sql>

    <select id="getCntyPoint" resultMap="pointModelResult">

        SELECT

        <include refid="BASE_COLUMN"></include>

        FROM

        <include refid="BASE_TABLE"/>

        WHERE gid=#{gId}

    </select>

    <insert id="insertCntyPoint" parameterType="com.history.gismap.model.PointModel">

        INSERT INTO

        <include refid="BASE_TABLE"/>

        <trim prefix="(" suffix=")" suffixOverrides=",">

            <if test="gId != null">

                gid,

            </if>

            <if test="nameCh != null">

                name_ch,

            </if>

            <if test="geometry != null">

                geom,

            </if>

        </trim>

        <trim prefix="VALUES(" suffix=")" suffixOverrides=",">

            <if test="gId != null">

                #{gId, jdbcType=BIGINT},

            </if>

            <if test="nameCh != null">

                #{nameCh, jdbcType=VARCHAR},

            </if>

            <if test="geometry != null">

                #{geometry,typeHandler=com.history.gismap.mybatis.GeometryTypeHandler}

            </if>

        </trim>

    </insert>

    <update id="updateCntyPoint" parameterType="com.history.gismap.model.PointModel">

        UPDATE

        <include refid="BASE_TABLE"/>

        SET

            name_ch=#{nameCh},

            geom=#{geometry,typeHandler=com.history.gismap.mybatis.GeometryTypeHandler}

        WHERE

        gid=#{gId}

    </update>

    <delete id="deleteCntyPoint" parameterType="com.history.gismap.model.PointModel">

        DELETE FROM

        <include refid="BASE_TABLE"/>

        WHERE

        gid=#{gId}

    </delete>

</mapper>      

六、修改service

Service沒改。

D:\gismap\java\gismap\src\main\java\com\history\gismap\service\MapService.java

package com.history.gismap.service;



import com.history.gismap.model.PointModel;

import org.springframework.stereotype.Service;



import java.util.List;

public interface MapService {

    List<PointModel> getCntyPointByGid(Integer gId);

    int addCntyPoint(PointModel pointModel);

    int modifyCntyPoint(PointModel pointModel);

    int removeCntyPoint(Integer gId);



}      

impl也沒有變動。

D:\gismap\java\gismap\src\main\java\com\history\gismap\service\impl\MapServiceImpl.java

package com.history.gismap.service.impl;



import com.history.gismap.dao.MapDao;

import com.history.gismap.model.PointModel;

import com.history.gismap.service.MapService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;



import java.util.List;

@Service

public class MapServiceImpl implements MapService {

    @Autowired

    private MapDao mapDao;

    @Override

    public List<PointModel> getCntyPointByGid(Integer gId){

        return mapDao.getCntyPoint(gId);

    }

    @Override

    public int addCntyPoint(PointModel pointModel){

        return mapDao.insertCntyPoint(pointModel);

    }

    @Override

    public int modifyCntyPoint(PointModel pointModel){

        return mapDao.updateCntyPoint(pointModel);

    }

    @Override

    public int removeCntyPoint(Integer gId){

        return mapDao.deleteCntyPoint(gId);

    }

}      

七、修改controller

為了便于前端讀寫,我們要把geometry對象轉化成geojson。

這個改動比較大,查詢傳回結果、增加入參、修改入參都改成了json格式,WKTReader用來讀取WKT文本,mybatis自定義引擎中引入的WKBReader是用來讀geohash文本的。

package com.history.gismap.controller;



import com.alibaba.fastjson.JSONArray;

import com.alibaba.fastjson.JSONObject;

import com.alibaba.fastjson.JSONPath;

import com.history.gismap.model.PointModel;

import com.history.gismap.service.MapService;

import com.vividsolutions.jts.geom.Coordinate;

import com.vividsolutions.jts.geom.Geometry;

import com.vividsolutions.jts.geom.GeometryFactory;

import com.vividsolutions.jts.geom.Point;

import com.vividsolutions.jts.io.ParseException;

import com.vividsolutions.jts.io.WKTReader;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.*;

@Controller

@RequestMapping(value = "/history")

public class MapController {

    @Autowired

    private MapService mapService;

    @ResponseBody

    @GetMapping("/pointmodel")

    public JSONObject getPoint(@RequestParam("gid") Integer gId){

        PointModel pointModel=mapService.getCntyPointByGid(gId).get(0);

        JSONObject jsonObject=new JSONObject();

        jsonObject.put("gid",pointModel.getGId());

        jsonObject.put("namech",pointModel.getNameCh());

        JSONObject geometry=new JSONObject();

        geometry.put("type",pointModel.getGeometry().getGeometryType());

        JSONArray coordinateArray=new JSONArray();

        Coordinate[] coordinates=pointModel.getGeometry().getCoordinates();

        JSONObject coor=new JSONObject();

        coor.put("longitude",coordinates[0].x);

        coor.put("latitude",coordinates[0].y);

        coordinateArray.add(coor);

        geometry.put("coordinate",coordinateArray);

        jsonObject.put("geometry",geometry);

        return jsonObject;

    }

    @ResponseBody

    @PostMapping("/add")

    public int addPoint(@RequestBody JSONObject request){

        PointModel pointModel=new PointModel();

        pointModel.setGId((Integer) JSONPath.eval(request,"$.gId"));

        pointModel.setNameCh((String) JSONPath.eval(request,"$.nameCh"));

        String pointStr= (String) JSONPath.eval(request,"$.point");

        GeometryFactory geometryFactory = new GeometryFactory();

        WKTReader reader = new WKTReader( geometryFactory );

        try {

            Geometry point = (Point) reader.read(pointStr);

            pointModel.setGeometry(point);

        } catch (ParseException e) {

            e.printStackTrace();

        }

        return mapService.addCntyPoint(pointModel);

    }

    @ResponseBody

    @PostMapping("/modify")

    public int update(@RequestBody JSONObject request){

        PointModel pointModel=new PointModel();

        pointModel.setGId((Integer) JSONPath.eval(request,"$.gId"));

        pointModel.setNameCh((String) JSONPath.eval(request,"$.nameCh"));

        String pointStr= (String) JSONPath.eval(request,"$.point");

        GeometryFactory geometryFactory = new GeometryFactory();

        WKTReader reader = new WKTReader( geometryFactory );

        try {

            Geometry point = (Point) reader.read(pointStr);

            pointModel.setGeometry(point);

        } catch (ParseException e) {

            e.printStackTrace();

        }

        return mapService.modifyCntyPoint(pointModel);

    }

    @ResponseBody

    @GetMapping("/remove")

    public int removetPoint(@RequestParam("gid") Integer gId){

        return mapService.removeCntyPoint(gId);

    }

}      

八、啟動測試

啟動工程D:\gismap\java\gismap\src\main\java\com\history\gismap\GismapApplication.java,用postman看下。

先看下查詢的結果:

通路http://localhost:8080/history/pointmodel?gid=1

{

    "gid": 1,

    "geometry": {

        "coordinate": [

            {

                "latitude": 39.012409,

                "longitude": 111.079483

            }

        ],

        "type": "Point"

    },

    "namech": "保德州"

}

新增結果:

http://localhost:8080/history/add

post一下。

{

       "gId":14357,

       "nameCh":"test",

       "point":"POINT (109.013388 32.715519)"

}

修改結果:

http://localhost:8080/history/modify

{

       "gId":14357,

       "nameCh":"test",

       "point":"POINT (0 0)"

}

從零開始,建構電子地圖網站:0_8_mybatis+TypeHandler+jts處理geometry一、引入依賴二、增加mybatis自定義類三、修改model四、修改dao五、修改mapper六、修改service七、修改controller八、啟動測試九、送出git,從git上pull分支

九、送出git,從git上pull分支

處理geometry對象就到這裡了。

把程式送出到git上。

本例程式在https://github.com/yimengyao13/gismap.git上,但是為了不和之前的程式沖突,是以建立了一個分支geometry。

切換新分支,右下角Git:master,點開Git Branchs——+New Branch;

寫上新分支名稱,也就是geometry,勾選Checkout branch,點選ok。

從零開始,建構電子地圖網站:0_8_mybatis+TypeHandler+jts處理geometry一、引入依賴二、增加mybatis自定義類三、修改model四、修改dao五、修改mapper六、修改service七、修改controller八、啟動測試九、送出git,從git上pull分支

這樣就可以線上上pull代碼下來了。

VCS——Git——Pull

從零開始,建構電子地圖網站:0_8_mybatis+TypeHandler+jts處理geometry一、引入依賴二、增加mybatis自定義類三、修改model四、修改dao五、修改mapper六、修改service七、修改controller八、啟動測試九、送出git,從git上pull分支

先重新整理下,選擇分支,pull。

從零開始,建構電子地圖網站:0_8_mybatis+TypeHandler+jts處理geometry一、引入依賴二、增加mybatis自定義類三、修改model四、修改dao五、修改mapper六、修改service七、修改controller八、啟動測試九、送出git,從git上pull分支

這樣就可以看代碼了。

接下來要把這個工程完善,因為三張表的其他屬性都要加載進來,而且web顯示,不能僅僅讀資料庫,這個太慢了,要把資料加載到記憶體中,以便于快速讀取。

一樣一樣來。

先把整個增删改查完善後,再進行記憶體加載。

繼續閱讀