Postgis - 如何通过 JDBC 使用数据类型 'geography'
Postgis - How to work with data type 'geography' via JDBC
正在使用 postgresql 9.3
postgis 2.1
.
进行 Web 项目
table中有一个geography
类型的列,它只存储了一个point
。
现在我需要通过 JDBC 和 Java 对象插入/select 类型。
阅读 postgis
手册后,没有找到太多相关信息。
题目是:
- 在 java pojo 模型 class 中,列应使用哪种 Java 数据类型?
- 如何写插入sql?
- 如何编写 select sql 来检索值并放入 Java 对象?
- 如果使用
mybatis
,是否影响上述问题的答案?
POINT
几何不需要特殊类型。只需使用像 double
这样的原始数据类型作为坐标。
例如,要通过 lon
和 lat
参数插入新的 geography
类型,请使用 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;
还有其他 input/output 格式,例如 GeoJSON、WKT 等
如果你使用的是Mybatis,你可以使用TypeHandler透明地进行纬度和经度之间的转换。以下是我在像您的 PostGIS、Mybatis 和 Gegraphy 需要的场景中是如何做到的。使用 TypeHandler 可以处理不同的 classes,您可以将几何类型包装到其中。在我的例子中,坐标有两个 double
属性,latitude
和 longitude
.
坐标class
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 的界面上准备 select。参考这里的用法'as coordinate'
,是说让ibatis去寻找坐标类型的表示,就是你刚才定义的CoordinateTypeHandler
处理的
重要的是要知道下面的 location
在您的 table 定义中被声明为 location geography(POINT, 4326)
。
@Select("SELECT " +
"ST_AsText(location) AS coordinate" +
"FROM " +
"mytable " +
"WHERE " +
"tableattribute = #{myattribute}")
List<Result> myFindMethod(
@Param("myattribute") Integer myattribute
);
此解决方案将为 class 的 Coordinate-kind 提供干净的抽象,将 latitude
和 longitude
属性包装到 PostGIS 上的 SRID=4326;POINT(2.294801 48.858007)
表示。考虑到 Mike T. 的解决方案,您需要为要在 API/service.
上创建的每个查询重写相同的 (ST_SetSRID(ST_MakePoint(:lon, :lat), 4326)::geography)
使用 TypeHandler
旨在避免这种情况,一旦您 change/add 表示您 TypeHandler
,它会直接反映在您使用的每个查询中 as coordinate
.
如果你使用 MyBatis,MyBatis 中有一个 Postgis 类型的小项目。并且已经添加到maven central,可以直接从maven中使用
正在使用 postgresql 9.3
postgis 2.1
.
table中有一个geography
类型的列,它只存储了一个point
。
现在我需要通过 JDBC 和 Java 对象插入/select 类型。
阅读 postgis
手册后,没有找到太多相关信息。
题目是:
- 在 java pojo 模型 class 中,列应使用哪种 Java 数据类型?
- 如何写插入sql?
- 如何编写 select sql 来检索值并放入 Java 对象?
- 如果使用
mybatis
,是否影响上述问题的答案?
POINT
几何不需要特殊类型。只需使用像 double
这样的原始数据类型作为坐标。
例如,要通过 lon
和 lat
参数插入新的 geography
类型,请使用 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;
还有其他 input/output 格式,例如 GeoJSON、WKT 等
如果你使用的是Mybatis,你可以使用TypeHandler透明地进行纬度和经度之间的转换。以下是我在像您的 PostGIS、Mybatis 和 Gegraphy 需要的场景中是如何做到的。使用 TypeHandler 可以处理不同的 classes,您可以将几何类型包装到其中。在我的例子中,坐标有两个 double
属性,latitude
和 longitude
.
坐标class
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 的界面上准备 select。参考这里的用法'as coordinate'
,是说让ibatis去寻找坐标类型的表示,就是你刚才定义的CoordinateTypeHandler
处理的
重要的是要知道下面的 location
在您的 table 定义中被声明为 location geography(POINT, 4326)
。
@Select("SELECT " +
"ST_AsText(location) AS coordinate" +
"FROM " +
"mytable " +
"WHERE " +
"tableattribute = #{myattribute}")
List<Result> myFindMethod(
@Param("myattribute") Integer myattribute
);
此解决方案将为 class 的 Coordinate-kind 提供干净的抽象,将 latitude
和 longitude
属性包装到 PostGIS 上的 SRID=4326;POINT(2.294801 48.858007)
表示。考虑到 Mike T. 的解决方案,您需要为要在 API/service.
(ST_SetSRID(ST_MakePoint(:lon, :lat), 4326)::geography)
使用 TypeHandler
旨在避免这种情况,一旦您 change/add 表示您 TypeHandler
,它会直接反映在您使用的每个查询中 as coordinate
.
如果你使用 MyBatis,MyBatis 中有一个 Postgis 类型的小项目。并且已经添加到maven central,可以直接从maven中使用