MyBatis+PostgreSQL实现地理几何元素的增删改查

231 阅读3分钟

代码整体结构

mapElement实体类

/**  
 * @Author 不会笑的人是怪物  
 * @Date 2023年 02月 05日 16:27  
 */  
 
@Data  
@AllArgsConstructor  
@NoArgsConstructor  
public class MapElement {  
    private Long id;  // 数据库自增主键  
  
    private String name;  // 地图元素的名称(医院,银行,警察局等)  
  
    /**  
     *  地图元素(医院,银行,警察局)以点的形式存储  
     */  
    private Double latitude;  // 地图元素位置点的的纬度  
  
    private Double longitude;  // 地图元素位置点的经度  
  
    private String geoStr;  // 空间信息转换为字符串  
}

pom文件对PostgreSQL依赖

<!--引入数据源-->  
<dependency>  
    <groupId>com.alibaba</groupId>  
    <artifactId>druid</artifactId>  
    <version>1.1.12</version>  
</dependency>  
<dependency>  
    <groupId>org.postgresql</groupId>  
    <artifactId>postgresql</artifactId>  
    <version>42.5.1</version>  
</dependency>

application.yml配置文件

server:  
  port: 8086  
  
spring:  
  datasource:  
    driver-class-name: org.postgresql.Driver  
    url: jdbc:postgresql://localhost:5432/geo?useSSL=false  
    type: com.alibaba.druid.pool.DruidDataSource  
    username: postgres  
    password: 123456  
  
mybatis:  
  mapper-locations: classpath:mapper/*.xml  
  type-aliases-package: com.lucky.entity

数据库建表

建表sql语句

create table public.map_elements(
 id serial PRIMARY KEY NOT NULL,
 name varchar(32),
 longitude real,
 latitude real
 );
 
--表说明
COMMENT ON TABLE public.map_elements IS '地图信息表';
--字段说明
COMMENT ON COLUMN public.map_elements.id IS '主键ID';
COMMENT ON COLUMN public.map_elements.name IS '地图元素名称';
COMMENT ON COLUMN public.map_elements.longitude IS '地图元素位置经度';
COMMENT ON COLUMN public.map_elements.latitude IS '地图元素位置经度';

添加地理几何信息列

select AddGeometryColumn('public', 'map_elements', 'element_location', 4326, 'POINT', 2)
  • 添加几何信息列这一步如果报错AddGeometryColumn函数不存在,是因为安装的postgis并没有添加到本数据库,在sql运行工具中执行下面语句即可
create extension postgis
  • 在建立数据表中,PostgreSQL中主键自增的设置相比mySQL要麻烦一下,除了id的类型要设置为serial外,还需要运行一个sql语句
CREATE SEQUENCE map_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
 
alter table map_elements alter column id set default nextval('map_id_seq');

实现对数据的增删改

  • mybatis的mapper.xml配置文件
  • resultMap是数据库字段与java pojo字段的一个映射
<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper  
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<mapper namespace="com.lucky.mapper.MapElementMapper">  
    <resultMap id="MapElementMap" type="MapElement">  
        <id property="id" column="id"/>  
        <result property="name" javaType="String" jdbcType="VARCHAR" column="name"/>  
        <result property="latitude" javaType="double" jdbcType="REAL" column="latitude"/>  
        <result property="longitude" javaType="double" jdbcType="REAL" column="longitude"/>  
        <result property="geoStr" javaType="String" jdbcType="VARCHAR" column="element_location"/>  
    </resultMap>  
</mapper>

数据的增加

controller层

  • geometryToString是一个把经纬度转换为字符串的函数,此处我把它作为一个单独的函数放在了controller层,实际项目开发中,可以视情况放在utils数据包中。
/**  
 * @Author 不会笑的人是怪物  
 * @Date 2023年 02月 05日 16:41  
 */  
 
@Slf4j  
@RestController  
public class MapElementController { 

    @Resource  
    private MapElementService mapElementService;  
  
    /**  
     * 添加地图元素  
     * @param mapElement  
     * @return 添加的地理元素信息  
     */  
    @PostMapping("/map")  
    public MapElement insertMapElement(@RequestBody MapElement mapElement) {  
        mapElement.setGeoStr(geometryToString(mapElement.getLongitude(), mapElement.getLatitude()));  
        mapElementService.insertMapElement(mapElement);  
        Long id = mapElement.getId();  
        return mapElementService.getMapElementById(id);  
    }  
  
    /**  
     * 将经纬度转换为字符串  
     * @param longitude  
     * @param latitude  
     * @return  
     */  
    private String geometryToString(double longitude, double latitude) {  
        String geoStr = "POINT" + "(" + longitude + " " + latitude + ")";  
        return geoStr;  
    }  
}

mapper层


/**  
 * @Author 不会笑的人是怪物  
 * @Date 2023年 02月 05日 16:34  
 */  
 
@Mapper  
public interface MapElementMapper {  
  
    /**  
     * 添加地图元素  
     *  
     * @param mapElement  
     */  
    void insertMapElement(MapElement mapElement);  
  
    /**  
     * 根据id查找数据  
     * @param id  
     * @return 依据id返回数据  
     */  
    MapElement getMapElementById(Long id);  
}

service层

service接口

/**  
 * @Author 不会笑的人是怪物  
 * @Date 2023年 02月 05日 16:41  
 */  
 
public interface MapElementService {  
  
    /**  
     * 根据id查找数据   
     * @param id  
     * @return 依据id返回数据  
     */  
    MapElement getMapElementById(Long id);  
    
    /**  
     * 添加地图元素  
     * @param mapElement  
     */  
    void insertMapElement(MapElement mapElement);  
}

service实现

/**  
 * @Author 不会笑的人是怪物  
 * @Date 2023年 02月 05日 16:42  
 */  
 
@Service  
public class MapElementServiceImpl implements MapElementService {  
  
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")  
  
    @Resource  
    private MapElementMapper mapElementMapper;  
    
    @Override  
    public MapElement getMapElementById(Long id) {  
        return mapElementMapper.getMapElementById(id);  
    }  
  
    @Override  
    public void insertMapElement(MapElement mapElement) {  
        mapElementMapper.insertMapElement(mapElement);  
    }  
}

映射文件中的sql语句

<!--根据id查找数据-->  
<!--MapElement getMapElementById(Long id);-->  
<select id="getMapElementById" parameterType="Long" resultMap="MapElementMap">  
    SELECT id,  
           name,
           longitude,
           latitude,
		   ST_AsGeoJson(element_location) as element_location
		   FROM map_elements
		   where id = #{id}
</select>  
 
<!--添加地图元素-->  
<!--void insertMapElement(MapElement mapElement);-->  
<insert id="insertMapElement" parameterType="MapElement" useGeneratedKeys="true" keyProperty="id">  
    <selectKey keyProperty="id" resultType="Long" order="BEFORE">  
        SELECT nextval('map_elements_id_seq'::regclass)  
    </selectKey>  
    insert into map_elements(name, longitude, latitude, element_location)  
    values (#{name}, #{longitude}, #{latitude}, ST_GeomFromText(#{geoStr}, 4326))
</insert>
  • ST_GeomFromText是PostGis自带的函数,用以把文本信息转换成对应的地理几何信息

  • ST_AsGeoJson是把几何地理信息转换成json字符串的函数

  • 在添加一条数据,不用传入id,id是主键自增的。数据添加完毕以后,需要依据本地数据的id得到添加的数据。

useGeneratedKeys="true" keyProperty="id"
  • 这句话意思就是返回添加数据后自动生成的主键id,这是PostgreSQL所特有的生成自增主键的方法,相比mySQL会麻烦一些
<selectKey keyProperty="id" resultType="Long" order="BEFORE">
    SELECT nextval('map_elements_id_seq'::regclass)
</selectKey>