如何通过JDBI绑定JTS Geometry类型适配PostgreSQL几何类型
解决方案
报错原因
JDBI默认没有内置com.vividsolutions.jts.geom.Geometry类型的参数绑定逻辑,你通过bindBean()绑定该类型字段时,找不到对应的参数工厂完成Java类型到PostgreSQL几何类型的转换,因此抛出该异常。
最优实现方案
采用「自定义ArgumentFactory + ColumnMapper」的方案,一次注册全局生效,适配bindBean()自动绑定逻辑,无需额外修改现有业务代码。
步骤1:引入必要依赖
确保项目中已引入PostGIS JDBC适配器与JTS依赖(Maven示例):
<dependency> <groupId>org.postgis</groupId> <artifactId>postgis-jdbc</artifactId> <version>2.5.1</version> <!-- 适配你的PostgreSQL服务版本 --> </dependency> <dependency> <groupId>com.vividsolutions</groupId> <artifactId>jts-core</artifactId> <version>1.14.0</version> <!-- 和你现有使用的版本保持一致 --> </dependency>
步骤2:实现Geometry参数工厂
自定义ArgumentFactory,完成JTS Geometry到PostGIS数据库类型的转换:
import com.vividsolutions.jts.geom.Geometry; import org.jdbi.v3.core.argument.AbstractArgumentFactory; import org.jdbi.v3.core.argument.Argument; import org.jdbi.v3.core.config.ConfigRegistry; import org.postgis.PGgeometry; import org.postgis.jts.JtsGeometry; import java.sql.Types; public class GeometryArgumentFactory extends AbstractArgumentFactory<Geometry> { public GeometryArgumentFactory() { super(Types.OTHER); } @Override protected Argument build(Geometry value, ConfigRegistry config) { return (position, statement, ctx) -> { PGgeometry pgGeometry = new JtsGeometry(value); statement.setObject(position, pgGeometry); }; } }
步骤3:实现Geometry结果映射器
如果需要将查询返回的几何字段自动映射为JTS Geometry类型,同步实现ColumnMapper:
import com.vividsolutions.jts.geom.Geometry; import org.jdbi.v3.core.mapper.ColumnMapper; import org.jdbi.v3.core.statement.StatementContext; import org.postgis.PGgeometry; import org.postgis.jts.JtsGeometry; import java.sql.ResultSet; import java.sql.SQLException; public class GeometryColumnMapper implements ColumnMapper<Geometry> { @Override public Geometry map(ResultSet r, int columnNumber, StatementContext ctx) throws SQLException { PGgeometry pgGeom = (PGgeometry) r.getObject(columnNumber); if (pgGeom instanceof JtsGeometry) { return ((JtsGeometry) pgGeom).getGeometry(); } return null; } }
步骤4:全局注册到JDBI实例
初始化JDBI时注册上述组件,后续所有bindBean()操作都会自动适配Geometry类型字段:
Jdbi jdbi = Jdbi.create(dataSource); jdbi.registerArgument(new GeometryArgumentFactory()); jdbi.registerColumnMapper(Geometry.class, new GeometryColumnMapper());
验证使用
你的业务代码无需做任何修改,正常使用bindBean()绑定包含Geometry字段的Bean即可:
// 示例Bean定义 public class GeoEntity { private Long id; private Geometry point; // 省略getter/setter } // 插入示例 jdbi.useHandle(handle -> { handle.createUpdate("INSERT INTO geo_table (id, point) VALUES (:id, :point)") .bindBean(new GeoEntity(1L, yourGeometryObject)) .execute(); });
内容的提问来源于stack exchange,提问作者oshai
相关产品推荐
相关产品推荐

