- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如果您使用 javascript 库“Leaflet”及其插件“Draw”,那么您可以检索如下所示的 geojson:
{
"type" : "Polygon",
"coordinates" : [ [ [ 13.95938491821289, 53.41329518072117 ], [ 14.955865859985348, 54.412618223375205 ], [ 13.9606294631958, 54.4120067663998 ], [ 13.95938491821289, 53.41329518072117 ] ] ]
}
如果您将上述 json 发送到网络服务器(使用 Java 代码,例如 Play Framework),那么我想知道在 postgis 数据库中插入或更新它的最简单方法,无需使用用于创建 sql 字符串的字符串连接。事实上,它可以创建具有上述结构的 SQL 字符串,但您希望避免字符串连接,这就是我关于如何改为使用PreparedStatement 占位符的问题的原因。例如,以下 SQL 代码可以直接从 pgAdmin 执行(也可以通过 JDBC 代码):
UPDATE polygons
SET
geom = ST_SetSRID(ST_GeomFromGeoJSON
('{
"type" : "Polygon",
"coordinates" : [ [ [ 13.95938491821289, 53.41329518072117 ], [ 14.955865859985348, 54.412618223375205 ], [ 13.9606294631958, 54.4120067663998 ], [ 13.95938491821289, 53.41329518072117 ] ] ]
}'), 26918)
WHERE polygonid = 1;
但是,正如大多数开发人员已经了解到的那样,我们应该避免字符串连接,而是使用占位符,例如如果使用PreparedStatement(或者例如如果使用Spring框架则使用JdbcTemplate)。
下面是一些代码来说明什么有效,什么无效。
我正在使用的 PostGIS 数据库表是使用以下语句创建的:
CREATE TABLE polygons (
polygonid serial NOT NULL,
geom geometry(Polygon,26918),
CONSTRAINT polygon_pkey PRIMARY KEY (polygonid)
);
在我的 Maven 文件 pom.xml 中,我使用此依赖项:
<dependency>
<groupId>net.postgis</groupId>
<artifactId>postgis-jdbc</artifactId>
<version>2.2.0</version>
</dependency>
Java代码:
import java.sql.*;
import org.postgis.PGgeometry;
...
// For verbosity reasons, I am below not including
// any try/catch/throw statements or any closings of connections/statements/recordsets
String url = "jdbc:postgresql://localhost:5432/nameOfYourDatabase";
Connection connection = DriverManager.getConnection(url, "postgres", "[YOUR_PASSWORD]");
// First below is some SQL query code which works and thus
// proves that the setup with jar files and database connection indeed works:
long maxPolygonId = 100L;
PreparedStatement ps = connection.prepareStatement(
"SELECT polygonid , geom FROM polygons WHERE polygonid < ?"
);
ps.setLong(1, maxPolygonId);
ResultSet rs = ps.executeQuery();
while(rs.next()) {
long polygonId = rs.getLong(1);
// Actually it works to use PGgeometry as below WITHOUT first having to do
// "((org.postgresql.PGConnection)conn).addDataType("geometry",Class.forName("org.postgis.PGgeometry"));"
// as currently documented at http://postgis.net/docs/ch06.html#idp48666800
PGgeometry geom = (PGgeometry)rs.getObject(2);
System.out.println("polygonId: " + polygonId);
System.out.println("geom: " + geom); // e.g. "geom: SRID=26918;POLYGON((17.9661226272583 59.41375375704178, ... ,17.9661226272583 59.41375375704178))"
}
// Below is some code that also indeed works fine but it uses string
// concatenation for the json string instead of placeholder which I want to use instead
String geoJson =
" { " +
" \"type\" : \"Polygon\", " +
" \"coordinates\" : [ [ [ 13.95938491821289, 53.41329518072117 ], [ 14.955865859985348, 54.412618223375205 ], [ 13.9606294631958, 54.4120067663998 ], [ 13.95938491821289, 53.41329518072117 ] ] ] " +
" } ";
String sqlUpdatingWithGeoJson =
" UPDATE polygons " +
" SET " +
" geom = ST_SetSRID(ST_GeomFromGeoJSON " +
" (' " +
geoJson +
" '), 26918) " +
" WHERE polygonid = ? ";
long idForPolygonToUpdate = 1L;
ps = connection.prepareStatement(sqlUpdatingWithGeoJson);
ps.setLong(1, idForPolygonToUpdate);
ps.executeUpdate();
// Below is some code which does NOT work when I am trying
// to use placeholder instead of string concatenation as above
String sqlUpdatingWithGeoJsonAsPlaceHolder =
" UPDATE polygons " +
" SET " +
" geom = ST_SetSRID(ST_GeomFromGeoJSON " +
" (' " +
" ? " + // NOTE that this line is the difference with the sql update string above !
" '), 26918) " +
" WHERE polygonid = ? ";
ps = connection.prepareStatement(sqlUpdatingWithGeoJsonAsPlaceHolder);
ps.setString(1, geoJson);
ps.setLong(2, idForPolygonToUpdate);
// The above row results in the exception below
// org.postgresql.util.PSQLException: The column index is out of range: 2, number of columns: 1.
ps.executeUpdate();
// Below I instead tried to replace the whole expression as a string to be set
// through the placeholder but it does NOT work neither
String geomValue =
" ST_SetSRID(ST_GeomFromGeoJSON " +
" (' " +
geoJson +
" '), 26918) ";
String sqlUpdatingWithPostGisStatementForPlaceHolder =
" UPDATE polygons " +
" SET " +
" geom = ? " +
" WHERE polygonid = ? ";
ps = connection.prepareStatement(sqlUpdatingWithPostGisStatementForPlaceHolder);
ps.setString(1, geomValue); // I have also tried setObject instead of setString here
ps.setLong(2, idForPolygonToUpdate);
// The above row also results in the same exception as previous above i.e. below exception:
// org.postgresql.util.PSQLException: The column index is out of range: 2, number of columns: 1.
ps.executeUpdate();
也许解决方案是将 json 字符串转换为一些可以理解的 Java 对象通过 PostGIS/PostgreSQL JDBC 驱动程序,然后使用方法“prepareStatement.setObject”,但是该 Java 对象应该使用什么类型以及如何轻松地将 json 字符串转换为这样的对象?
最佳答案
String sqlUpdatingWithGeoJsonAsPlaceHolder =
" UPDATE polygons " +
" SET " +
" geom = ST_SetSRID(ST_GeomFromGeoJSON(?), 26918) " +
" WHERE polygonid = ? ";
ps = connection.prepareStatement(sqlUpdatingWithGeoJsonAsPlaceHolder);
ps.setString(1, geoJson);
ps.setLong(2, idForPolygonToUpdate);
ps.executeUpdate();
这个应该可以工作:您将 geojson 作为字符串传递。函数 ST_GeomFromGeoJSON 需要一个字符串作为第一个参数,因此可以准备并执行该语句。
您收到该错误是因为您引用了问号。这样,问号就不会被解释为占位符!
关于java - 如何使用 Java JDBCPreparedStatement 占位符将 GeoJSON 多边形插入 PostGIS 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36664739/
鉴于 PreparedStatement 的以下代码,我使用占位符 (?) 来填充 String: String sql = "SELECT SUM(Premium), SUM(AgentComm)\
当我想将PreparedStatement初始化用于给定类的所有实例时,放置PreparedStatement初始化的最佳位置是什么? 到目前为止,我的解决方案是创建用于打开和关闭的静态方法,但我认为
我正在尝试使用PreparedStatement 进行批量更新,其中您获取的数据因可用数据而异。 简单的例子: 您有一个包含 x 列和 y 列的表。您的输入数据是仅存在修改后的列的行的表示。因此,对于
这个问题已经有答案了: Variable column names using prepared statements (7 个回答) 已关闭 6 年前。 我与 Oracle 数据库的连接如下: St
有人可以告诉我为什么准备好的语句返回 null 吗?下面是查询数据库的代码: package beans; import java.sql.*; public class ConnectToDB {
我目前正在编写一个与 Oracle 数据库交互的 Java Web 应用程序。我正在使用PreparedStatements,因为Hibernate 会使事情变得太复杂。 由于写入数据库的程序中存在错
我正在使用 JDBC 连接从 Access 数据库获取数据。数据库设计不是我的控制。数据库中有些列带有“?”包含在他们的名称中,例如:Open?、Paid? 等等。 当我尝试使用PreparedSta
这个问题已经有答案了: Variable column names using prepared statements (7 个回答) 已关闭 6 年前。 我与 Oracle 数据库的连接如下: St
这个问题与 Using query_to_xml in PostgreSQL with prepared statements 非常相似但是那里的解决方案似乎不适用于我的情况。这实际上是一个非常奇怪的
我正在使用 Xerials SQLite JDBC 驱动程序,并且想要做您能想象到的最简单的事情: 我创建了下表: CREATE TABLE IF NOT EXISTS households (hos
这个问题已经有答案了: Inserting null to an Integer column using JDBC (2 个回答) 已关闭 5 年前。 当使用原始 JDBC 时,您可以参数化 Pre
我正在使用 postgres 数据库并使用 JDBC。大多数事情都工作正常,但我在这段代码中遇到以下错误,似乎我没有正确使用 setString/setDate 与$ 风格的参数化查询。废话不多说,代
我认为我的 Oracle JDBC 准备语句遗漏了一些明显的内容。我正在尝试创建一个从 TABLE 中选择列 A 的 PreparedStatement ,其中 B 是参数。例如,这也是我总结的测试代
我有一个java中的PreparedStatement。我向它提供包含“?”的查询,例如 Select .... where date >= ? 这没问题,当我尝试使用以下方法设置参数时: prepa
如果您使用 javascript 库“Leaflet”及其插件“Draw”,那么您可以检索如下所示的 geojson: { "type" : "Polygon", "coordinat
我是Java中PreparedStatement的新手,我似乎无法找出解决我的问题的最佳解决方案。我想查询表中 NULL 或 NOT NULL 的记录。 阅读PreparedStatement (Ja
try { Class.forName("org.apache.hive.jdbc.HiveDriver"); } catch (ClassNotFoundException
我是一名优秀的程序员,十分优秀!