引入pom
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.18.2</version>
</dependency>
mybatis-config.xml配置
<typeHandlers>
<typeHandler handler="com.test.domain.gis.GeometryTypeHandler"
javaType="com.test.domain.gis.GeometryPoint" jdbcType="VARCHAR"/>
<typeHandler handler="com.test.domain.gis.GeometryTypeHandler"
javaType="com.test.domain.gis.GeometryMultiPoint" jdbcType="VARCHAR"/>
<typeHandler handler="com.test.domain.gis.GeometryTypeHandler"
javaType="com.test.domain.gis.GeometryLineString" jdbcType="VARCHAR"/>
<typeHandler handler="com.test.domain.gis.GeometryTypeHandler"
javaType="com.test.domain.gis.GeometryMultiLineString" jdbcType="VARCHAR"/>
<typeHandler handler="com.test.domain.gis.GeometryTypeHandler"
javaType="com.test.domain.gis.GeometryPolygon" jdbcType="VARCHAR"/>
<typeHandler handler="com.test.domain.gis.GeometryTypeHandler"
javaType="com.test.domain.gis.GeometryMultiPolygon" jdbcType="VARCHAR"/>
</typeHandlers>
类型转换器 配置
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.geom.impl.CoordinateArraySequenceFactory;
import org.locationtech.jts.io.ByteOrderValues;
import org.locationtech.jts.io.InputStreamInStream;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import static org.apache.ibatis.type.JdbcType.VARCHAR;
//@MappedTypes:指定与其关联的 Java类型列表。如果在javaType 属性中也同时指定,则注解上的配置将被忽略。
//@MappedJdbcTypes:指定与其关联的JDBC 类型列表。如果在jdbcType 属性中也同时指定,则注解上的配置将被忽略。
@MappedTypes({GeometryPoint.class, GeometryMultiPoint.class, GeometryLineString.class,GeometryMultiLineString.class,GeometryPolygon.class,GeometryMultiPolygon.class})
@MappedJdbcTypes(value = VARCHAR)
public class GeometryTypeHandler extends BaseTypeHandler<Object> {
/**
* Precision model
*/
private PrecisionModel precisionModel = new PrecisionModel();
/**
* Coordinate sequence factory
*/
private CoordinateSequenceFactory coordinateSequenceFactory = CoordinateArraySequenceFactory.instance();
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter1, JdbcType jdbcType) throws SQLException {
String paramSimpleName=parameter1.getClass().getSimpleName();
if("GeometryPoint".equals(paramSimpleName)){
ps.setString(i, toSqlPoint(toPointStr((GeometryPoint) parameter1)) );
}
else if("GeometryMultiPoint".equals(paramSimpleName)){
ps.setString(i, toSqlMultiPoint(appendPoint(((GeometryMultiPoint) parameter1).getMultiPoint()) ));
}
else if("GeometryLineString".equals(paramSimpleName)){
ps.setString(i, toSqlLineString(appendLine(((GeometryLineString) parameter1).getMultiPoint()) ));
}
else if("GeometryMultiLineString".equals(paramSimpleName)){
ps.setString(i, toSqlMultiLineString(appendMultiLine(((GeometryMultiLineString)parameter1).getMultiLine() ) ));
}
else if("GeometryPolygon".equals(paramSimpleName)){
// 点位要首尾一样
ps.setString(i, toSqlPolygon(appendPolygon(((GeometryPolygon) parameter1).getPolygon()) ));
}
else if("GeometryMultiPolygon".equals(paramSimpleName)){
ps.setString(i, toSqlMultipolygon(appendMultiPolygon(((GeometryMultiPolygon) parameter1).getMultiPolygon()) ));
}
}
private String appendPoint(List<GeometryPoint> ll){
StringBuilder sb =new StringBuilder();
for (int j = 0; j <ll.size() ; j++) {
sb.append(toPointStr(ll.get(j)));
if(j!=ll.size()-1){
sb.append(",");
}
}
return sb.toString();
}
private String appendLine(List<GeometryPoint> ll){
StringBuilder sb =new StringBuilder();
for (int j = 0; j <ll.size() ; j++) {
sb.append(toLineStr(ll.get(j)));
if(j!=ll.size()-1){
sb.append(",");
}
}
return sb.toString();
}
private String appendPolygon(List<GeometryPoint> ll){
StringBuilder sb =new StringBuilder();
sb.append("(");
for (int j = 0; j <ll.size() ; j++) {
sb.append(toLineStr(ll.get(j)));
if(j!=ll.size()-1){
sb.append(", ");
}
}
sb.append(")");
return sb.toString();
}
private String appendMultiPolygon(List<GeometryPolygon> ll){
StringBuilder sb =new StringBuilder();
sb.append("(");
for (int j = 0; j <ll.size() ; j++) {
sb.append(appendPolygon(ll.get(j).getPolygon()));
if(j!=ll.size()-1){
sb.append(", ");
}
}
sb.append(")");
return sb.toString();
}
private String appendMultiLine(List<GeometryLineString> ll){
StringBuilder sb =new StringBuilder();
for (int j = 0; j <ll.size() ; j++) {
sb.append("(");
sb.append(appendLine(ll.get(j).getMultiPoint()));
sb.append(")");
if(j!=ll.size()-1){
sb.append(",");
}
}
return sb.toString();
}
private String toSqlPoint(String str){
return StringUtils.format("POINT({})",str);
}
private String toSqlMultiPoint(String str){
return StringUtils.format("MULTIPOINT({})",str);
}
private String toSqlLineString(String str){
return StringUtils.format("LINESTRING({})",str);
}
private String toSqlMultiLineString(String str){
return StringUtils.format("MULTILINESTRING({})",str);
}
private String toSqlPolygon(String str){
return StringUtils.format("POLYGON({})",str);
}
private String toSqlMultipolygon(String str){
return StringUtils.format("MULTIPOLYGON({})",str);
}
private String toPointStr(GeometryPoint point){
return StringUtils.format("({} {})",point.getLat(),point.getLng());
}
private String toLineStr(GeometryPoint point){
return StringUtils.format("{} {}",point.getLat(),point.getLng());
}
@Override
public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
return from(rs.getBytes(columnName));
}
@Override
public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return from(rs.getBytes(columnIndex));
}
@Override
public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return from(cs.getBytes(columnIndex));
}
public Object from(byte[] bytes) {
if (bytes == null) {
return null;
}
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
// Read SRID
byte[] sridBytes = new byte[4];
inputStream.read(sridBytes);
int srid = ByteOrderValues.getInt(sridBytes, ByteOrderValues.LITTLE_ENDIAN);
// Prepare Geometry factory
GeometryFactory geometryFactory = new GeometryFactory(precisionModel, srid, coordinateSequenceFactory);
// Read Geometry
WKBReader wkbReader = new WKBReader(geometryFactory);
Geometry geometry = wkbReader.read(new InputStreamInStream(inputStream));
String geoClassSimpleName =geometry.getClass().getSimpleName();
if("MultiPoint".equals(geoClassSimpleName)){
GeometryMultiPoint geometryMultiPoint= new GeometryMultiPoint();
geometryMultiPoint.setMultiPoint(coordinateToGeoPoint(geometry.getCoordinates()));
return geometryMultiPoint;
}
if("LineString".equals(geoClassSimpleName)){
GeometryLineString geometryLineString= new GeometryLineString();
geometryLineString.setMultiPoint(coordinateToGeoPoint(geometry.getCoordinates()));
return geometryLineString;
}
if("MultiLineString".equals(geoClassSimpleName)){
GeometryMultiLineString geometryMultiLineString = new GeometryMultiLineString();
ArrayList<GeometryLineString> list = new ArrayList<>();
MultiLineString ml= (MultiLineString)geometry;
for (int i = 0; i <ml.getNumGeometries() ; i++) {
GeometryLineString one= new GeometryLineString();
one.setMultiPoint(coordinateToGeoPoint(ml.getGeometryN(i).getCoordinates()));
list.add(one);
}
geometryMultiLineString.setMultiLine(list);
return geometryMultiLineString;
}
if("Polygon".equals(geoClassSimpleName)){
GeometryPolygon geometryPolygon = new GeometryPolygon();
geometryPolygon.setPolygon(coordinateToGeoPoint(geometry.getCoordinates()));
return geometryPolygon;
}
if("MultiPolygon".equals(geoClassSimpleName)){
GeometryMultiPolygon geometryMultiPolygon = new GeometryMultiPolygon();
List<GeometryPolygon> list = new ArrayList<>();
for (int i = 0; i <geometry.getNumGeometries() ; i++) {
GeometryPolygon geometryPolygon = new GeometryPolygon();
geometryPolygon.setPolygon(coordinateToGeoPoint(geometry.getCoordinates()));
list.add(geometryPolygon);
}
geometryMultiPolygon.setMultiPolygon(list);
return geometryMultiPolygon;
}
Point point = (Point) geometry;
GeometryPoint geoPoint = new GeometryPoint(point.getX(), point.getY());
return geoPoint;
} catch (IOException | ParseException e) {
throw new IllegalArgumentException(e);
}
}
private List<GeometryPoint> coordinateToGeoPoint(Coordinate[] coordinates){
List<GeometryPoint> list=new ArrayList<>();
for (Coordinate coordinate : coordinates) {
list.add(new GeometryPoint(coordinate.getX(),coordinate.getY()));
}
return list;
}
}
java实体类 配置
GeometryPoint
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
/** 点**/
public class GeometryPoint implements Serializable {
/**
* 纬度
*/
private double lat;
/**
* 经度
*/
private double lng;
}
GeometryMultiPoint
@Data
@AllArgsConstructor
@NoArgsConstructor
/** 点集合 **/
public class GeometryMultiPoint implements Serializable {
private List<GeometryPoint> multiPoint;
}
GeometryLineString
@Data
@AllArgsConstructor
@NoArgsConstructor
/** 线 **/
public class GeometryLineString implements Serializable {
private List<GeometryPoint> multiPoint;
}
GeometryMultiLineString
@Data
@AllArgsConstructor
@NoArgsConstructor
/** 线集合 **/
public class GeometryMultiLineString implements Serializable {
private List<GeometryLineString> multiLine;
}
GeometryPolygon
@Data
@AllArgsConstructor
@NoArgsConstructor
/** 平面 **/
public class GeometryPolygon implements Serializable {
private List<GeometryPoint> polygon;
}
GeometryMultiPolygon
@Data
@AllArgsConstructor
@NoArgsConstructor
/** 平面集合 **/
public class GeometryMultiPolygon implements Serializable {
private List<GeometryPolygon> multiPolygon;
}
java传值对象属性
/** 点 */
@ApiModelProperty(value = "点")
private GeometryPoint pointDoubleDouble;
/** 点集合 */
@ApiModelProperty(value = "点集合")
private GeometryMultiPoint multipointDoubleDoubleArry;
/** 折线图 */
@ApiModelProperty(value = "折线图")
private GeometryLineString linestring;
/** 折线集合 */
@ApiModelProperty(value = "折线集合")
private GeometryMultiLineString multilinestring;
/** 平面 */
@ApiModelProperty(value = "平面")
private GeometryPolygon polygon;
/** 平面集合 */
@ApiModelProperty(value = "平面集合")
private GeometryMultiPolygon multipolygon;
mapper.xml 配置
insert 语句里
<if test="gisPoint != null">GeomFromText(#{gisPoint}),</if>
<if test="gisMultipoint != null">GeomFromText(#{gisMultipoint}),</if>
<if test="gisLineString != null">GeomFromText(#{gisLineString}),</if>
<if test="gisMultiLineString != null">GeomFromText(#{gisMultiLineString}),</if>
<if test="gisPolygon != null">GeomFromText(#{gisPolygon}),</if>
<if test="gisMultiPolygon != null">GeomFromText(#{gisMultiPolygon}),</if>