Java 定义类型处理MySQL point类型数据

9 篇文章 0 订阅

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;
    }


    @Override
    public 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 SRID
            byte[] sridBytes = new byte[4];
            inputStream.read(sridBytes);
            int srid = ByteOrderValues.getInt(sridBytes, byteOrder);
            // Prepare Geometry factory
            GeometryFactory geometryFactory = new GeometryFactory(precisionModel, srid, coordinateSequenceFactory);
            // Read Geometry
            WKBReader wkbReader = new WKBReader(geometryFactory);
            Geometry geometry = wkbReader.read(new InputStreamInStream(inputStream));
            Point point = (Point) geometry;
            // convert to GeoPoint
            GeoPoint 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 纬度 lat
        Coordinate 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 SRID
            byte[] sridBytes = new byte[4];
            ByteOrderValues.putInt(point.getSRID(), sridBytes, byteOrder);
            outputStream.write(sridBytes);
            // Write Geometry
            WKBWriter 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();
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, GeoPoint parameter, JdbcType jdbcType) throws SQLException {
        ps.setBytes(i, converter.to(parameter));
    }
    @Override
    public GeoPoint getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return converter.from(rs.getBytes(columnName));
    }
    @Override
    public GeoPoint getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return converter.from(rs.getBytes(columnIndex));
    }
    @Override
    public 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
{
    @Autowired
    private PositionInfoService positionInfoService;


    /**
     * 新增地理位置信息
     */
    @PostMapping
    public 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

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值