Postgis - 如何通过JDBC处理数据类型“地理”

时间:2015-04-20 10:03:42

标签: java postgresql jdbc postgis mybatis

处理使用postgresql 9.3 postgis 2.1

的网络项目

表格中有一个geography类型的列,它只存储point

现在我需要通过带有Java对象的JDBC插入/选择类型。

阅读postgis手册后,没有找到相关信息。

问题是:

  1. 在java pojo模型类中,应该为列使用什么Java数据类型?
  2. 如何编写insert sql?
  3. 如何编写select sql来检索值并放入Java对象?
  4. 如果使用mybatis,那么它是否会影响上述问题的答案?

3 个答案:

答案 0 :(得分:5)

POINT几何图形不需要特殊类型。只需使用double之类的原始数据类型作为坐标。

例如,要通过geographylon参数插入新的lat类型,请使用geometry constructor functions

INSERT INTO my_table (geog)
VALUES (ST_SetSRID(ST_MakePoint(:lon, :lat), 4326)::geography);

或者将它们作为浮点数返回,使用geometry accessor functions

SELECT ST_Y(geog::geometry) AS lat, ST_X(geog::geometry) AS lon FROM my_table;

还有其他输入/输出格式,如GeoJSON,WKT等。

答案 1 :(得分:2)

如果您使用MyBatis,MyBatis中有一个Postgis类型的小项目。它已添加到maven central,因此您可以直接从maven中使用它。

https://github.com/eyougo/mybatis-typehandlers-postgis

答案 2 :(得分:1)

如果您使用的是Mybatis,则可以使用TypeHandler透明地进行纬度和经度之间的转换。以下是我在像你,PostGIS,Mybatis和Gegraphy这样的场景中的表现。使用TypeHandler可以处理不同的类,您可以将几何类型包装到其中。在我的情况下,Coordinate有两个double属性,latitudelongitude

协调班级

public class Coordinate {
    private Double latitude;
    private Double latitude;
    ... getters, setters, etc
}

宣布Ibati的TypeHandler

@MappedJdbcTypes(JdbcType.JAVA_OBJECT)
@MappedTypes({Coordinate.class})
public class CoordinateTypeHandler extends BaseTypeHandler<Coordinate> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Coordinate parameter, JdbcType jdbcType) throws SQLException {
        // Convert Coordinate to Ibatis representation of Postgis point, e.g., "SRID=4326;POINT(2.294801 48.858007)"
        Point point = new Point(parameter.getLongitude(), parameter.getLatitude());
        point.setSrid(4326);
        ps.setString(i, point.toString());
    }

    // Convert data read from Ibatis to actual Coordinate class
    @Override
    public Coordinate getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return from(rs.getString(columnName));
    }

    @Override
    public Coordinate getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return from(rs.getString(columnIndex));
    }

    @Override
    public Coordinate getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return from(cs.getString(columnIndex));
    }

    protected Coordinate from(String pointAsText) throws SQLException {
        if (pointAsText != null) {
            Point point = new Point(pointAsText);
            return new Coordinate(point.getY(), point.getX());
        }
        return null;
    }
}

然后在Ibatis界面上准备你的选择。请参考此处的用法'as coordinate',它向Ibatis说要查找坐标类型的表示,该坐标类型由您刚刚定义的CoordinateTypeHandler处理。

重要的是要知道location贝娄在表定义中声明为location geography(POINT, 4326)

@Select("SELECT " +
        "ST_AsText(location) AS coordinate" +
    "FROM " +
        "mytable " +
    "WHERE " +
        "tableattribute = #{myattribute}")
List<Result> myFindMethod(
        @Param("myattribute") Integer myattribute
);

此解决方案将为Coordinate类提供一个干净的抽象,该类将latitudelongitude属性包装到PostGIS上的SRID=4326;POINT(2.294801 48.858007)表示中。考虑到Mike T.的解决方案,您需要为要在API /服务上创建的每个查询重写相同的(ST_SetSRID(ST_MakePoint(:lon, :lat), 4326)::geography)

使用TypeHandler旨在避免这种情况,一旦您更改/添加了TypeHandler的代表,它就会直接反映您使用的每个查询as coordinate