1.三个类来处理
引入maven依赖
<!-- 引入 jts 库解析 POINT --><dependency><groupId>com.vividsolutions</groupId><artifactId>jts</artifactId><version>1.13</version></dependency>
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.io.Serializable;/*** 经纬度对象* <br>* x 经度 lon 浮点数,范围为180 ~ -180 <br>* y 纬度 lat 浮点数,范围为90 ~ -90*/
public class GeoPoint implements Serializable {/*** 参数校验* 在lon、lat 字段添加@Min @Max 注解,并且在使用该类的地方加 @Valid 注解* 如:* @Valid* private GeoPoint lonlat;*/// controller @RequestBody 参数内嵌套对象,必须有一个无参的构造函数public GeoPoint() {}/*** 经度*/@Min(value = -180, message = "经度lon不能小于-180")@Max(value = 180, message = "经度lon不能大于180")private double lon;/*** 纬度*/@Min(value = -90, message = "纬度lat不能小于-90")@Max(value = 90, message = "纬度lat不能大于90")private double lat;/**** @param x 经度 lon 浮点数,范围为180 ~ -180* @param y 纬度 lat 浮点数,范围为90 ~ -90*/public GeoPoint(double x, double y) {this.lon = x;this.lat = y;}public double getLon() {return lon;}public void setLon(double lon) {this.lon = lon;}public double getLat() {return lat;}public void setLat(double lat) {this.lat = lat;}@Overridepublic String toString() {return "GeoPoint{" +"lon=" + lon +", lat=" + lat +'}';}}
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequenceFactory;
import com.vividsolutions.jts.io.*;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class GeoPointConverter {/*** Little endian or Big endian*/private int byteOrder = ByteOrderValues.LITTLE_ENDIAN;/*** Precision model*/private PrecisionModel precisionModel = new PrecisionModel();/*** Coordinate sequence factory*/private CoordinateSequenceFactory coordinateSequenceFactory = CoordinateArraySequenceFactory.instance();/*** Output dimension*/private int outputDimension = 2;/*** Convert byte array containing SRID + WKB Geometry into Geometry object*/public GeoPoint from(byte[] bytes) {if (bytes == null) {return null;}try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {// Read SRIDbyte[] sridBytes = new byte[4];inputStream.read(sridBytes);int srid = ByteOrderValues.getInt(sridBytes, byteOrder);// Prepare Geometry factoryGeometryFactory geometryFactory = new GeometryFactory(precisionModel, srid, coordinateSequenceFactory);// Read GeometryWKBReader wkbReader = new WKBReader(geometryFactory);Geometry geometry = wkbReader.read(new InputStreamInStream(inputStream));Point point = (Point) geometry;// convert to GeoPointGeoPoint geoPoint = new GeoPoint(point.getX(), point.getY());return geoPoint;} catch (IOException | ParseException e) {throw new IllegalArgumentException(e);}}/*** Convert Geometry object into byte array containing SRID + WKB Geometry*/public byte[] to(GeoPoint geoPoint) {if (geoPoint == null) {return null;}// @param x 经度 lon// @param y 纬度 latCoordinate coordinate = new Coordinate(geoPoint.getLon(), geoPoint.getLat());CoordinateArraySequence coordinateArraySequence = new CoordinateArraySequence(new Coordinate[]{coordinate}, 2);Point point = new Point(coordinateArraySequence, new GeometryFactory());try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {// Write SRIDbyte[] sridBytes = new byte[4];ByteOrderValues.putInt(point.getSRID(), sridBytes, byteOrder);outputStream.write(sridBytes);// Write GeometryWKBWriter wkbWriter = new WKBWriter(outputDimension, byteOrder);wkbWriter.write(point, new OutputStreamOutStream(outputStream));return outputStream.toByteArray();} catch (IOException ioe) {throw new IllegalArgumentException(ioe);}}
}
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.springframework.stereotype.Component;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;@Component //注入Bean,全局配置使其自动转换,不需要在sql层手动指定
@MappedJdbcTypes(JdbcType.OTHER) // JdbcType只能用OTHER类型,没有point类型
@MappedTypes(GeoPoint.class)
public class GeoPointTypeHandler extends BaseTypeHandler<GeoPoint> {GeoPointConverter converter = new GeoPointConverter();@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, GeoPoint parameter, JdbcType jdbcType) throws SQLException {ps.setBytes(i, converter.to(parameter));}@Overridepublic GeoPoint getNullableResult(ResultSet rs, String columnName) throws SQLException {return converter.from(rs.getBytes(columnName));}@Overridepublic GeoPoint getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return converter.from(rs.getBytes(columnIndex));}@Overridepublic GeoPoint getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return converter.from(cs.getBytes(columnIndex));}
}
2.使用
model中使用
public class PositionInfo implements Serializable
{private static final long serialVersionUID = 1L;/** 经纬度 */@Valid //接口中使用 @Valid 对参数 PositionInfo 进行校验,需要在这里也加@Valid 注解private GeoPoint lonlat;//....
}
controller
@Validated
@RestController
@RequestMapping("/positioninfo")
public class PositionInfoController
{@Autowiredprivate PositionInfoService positionInfoService;/*** 新增地理位置信息*/@PostMappingpublic Result addPositionInfo( @RequestBody @Valid PositionInfo positionInfo){System.err.println(positionInfo);return reult(positionInfoService.insertPositionInfo(positionInfo));}
DAO
@Select("select * from position_info_table")
// @Results(
// @Result(column = "lonlat",property = "lonlat",
// javaType = GeoPoint.class,typeHandler = GeoPointTypeHandler.class)
// )List<PositionInfo> listPositionInfo(PositionInfo positionInfo);@Insert("insert into position_info_table (lonlat) values (#{p.lonlat})" )int insertPositionInfo(@Param("p") PositionInfo positionInfo);
测试
--------
# 无效,解决:在GeoPointTypeHandler 使用 @Component
#配置point解析工具GeoPointTypeHandler,使其自动转换,不需要在sql层手动指定
#mybatis:
# type-handlers-package:com.jeaglo.auxpolice.tools