Postgis - How to work with data type 'geography' via JDBC

╄→гoц情女王★ 提交于 2019-12-11 09:31:23

问题


Working on a web project, which uses postgresql 9.3 postgis 2.1.

There is a column of type geography in the table, it just store a point.

Now I need to insert / select the type via JDBC with Java object.

After reading postgis manual, didn't find much information relevant.

The questions are:

  1. In java pojo model class, what Java data type should be used for the column?
  2. How to write the insert sql?
  3. How to write the select sql to retrieve the value and put into Java object?
  4. If mybatis is used, then does it effect answers to above questions?

回答1:


You don't need special types for POINT geometries. Just use primitive data types like double for the coordinates.

E.g., to insert a new geography type via lon and lat parameters, use geometry constructor functions:

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

Or get them back as floating point numbers, use geometry accessor functions:

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

There are other input/output formats, like GeoJSON, WKT, etc.




回答2:


If you use MyBatis, There is a tiny project for Postgis type in MyBatis. And it has been added to maven central, so you can use it directly from maven.

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




回答3:


If you are using Mybatis, you can have the conversion between latitude and longitude transparently made using a TypeHandler. Here is how I did it in a scenario like yours, PostGIS, Mybatis, and Gegraphy need. Using TypeHandler makes the handling of different classes you may wrap a geometry type into. In my case Coordinate has two double attributes, latitude and longitude.

Coordinate class

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

Declare Ibati's 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;
    }
}

Then prepare your select on Ibatis' interface. Refer to the usage 'as coordinate' here, it says to Ibatis to look for the representation of coordinate type, which is the handled by the CoordinateTypeHandler you just defined.

It is important to know that location bellow is declared as location geography(POINT, 4326) on your table definition.

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

This solution will provide a clean abstraction to the Coordinate-kind of class that wraps latitude and longitude attributes to the SRID=4326;POINT(2.294801 48.858007) representation on PostGIS. Considering the solution of Mike T., you would need to rewrite the same (ST_SetSRID(ST_MakePoint(:lon, :lat), 4326)::geography) for every query you are going to create on your API/service.

Using a TypeHandler aims to avoid that, once you change/add the representation of you TypeHandler, it reflects directly on every query you use as coordinate.



来源:https://stackoverflow.com/questions/29744816/postgis-how-to-work-with-data-type-geography-via-jdbc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!