代码整体结构
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>