1

在我的 PostgreSQL 12.2 + PostGIS 2.5.4 中,我有一个名为 Address 的表,其中有一列类型为geography(POINT, 4326).

我正在使用 Hibernate Spatial 并尝试开发一个属性转换器来从我的 SpatialLocation 对象创建预期的 Point 对象。

SpatialLocation 基本上具有坐标信息:

@Data
@Accessors(chain = true)
public class SpatialLocation {

    private Double latitude;

    private Double longitude;
}

这是我制作的 PointFactory 组件:

public class PointFactory extends GeometryFactory {

    public Point createPointFromSpatialLocation(SpatialLocation spatialLocation) {

        final Coordinate coordinate = new Coordinate(spatialLocation.getLatitude(), spatialLocation.getLongitude());

        return createPoint(coordinate);
    }

}

这是点转换器:

@Component
public class PointConverter implements AttributeConverter<SpatialLocation, Point> {

    @Autowired
    private PointFactory pointFactory;

    @Override
    public Point convertToDatabaseColumn(SpatialLocation spatialLocation) {
        return pointFactory.createPointFromSpatialLocation(spatialLocation);
    }

    @Override
    public SpatialLocation convertToEntityAttribute(Point point) {
        return new SpatialLocation()
                .setLatitude(point.getCoordinate().x)
                .setLongitude(point.getCoordinate().y);
    }

}

以下是在地址类上设置属性的方式:

    @Convert(converter = PointConverter.class)
    @Column(columnDefinition = "geography(POINT, 4326)")
    private SpatialLocation spatialLocation;

在服务上,地址是这样创建和保存的:

    @Transactional
    public Address saveAddress(final AddressRequest addressRequest) {

        final City city = findOrCreateNewCityService.findOrCreateNewCity(addressRequest.getCityRequest());

        final Address addressToPersist = modelMapper.map(addressRequest, Address.class)
                .setSpatialLocation(modelMapper.map(addressRequest.getSpatialLocationRequest(), SpatialLocation.class))
                .setCity(city);

        log.info("Creating a new Address: '{}'", addressToPersist);
        return addressRepository.save(addressToPersist);
    }

尝试创建新地址时,出现以下错误:

org.hibernate.HibernateException: Unknown unwrap conversion requested: com.vividsolutions.jts.geom.Geometry to [B
    at org.hibernate.type.descriptor.java.AbstractTypeDescriptor.unknownUnwrap(AbstractTypeDescriptor.java:98) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.spatial.JTSGeometryJavaTypeDescriptor.unwrap(JTSGeometryJavaTypeDescriptor.java:70) ~[hibernate-spatial-5.3.16.Final.jar:5.3.16.Final]
    at org.hibernate.spatial.JTSGeometryJavaTypeDescriptor.unwrap(JTSGeometryJavaTypeDescriptor.java:26) ~[hibernate-spatial-5.3.16.Final.jar:5.3.16.Final]
    at org.hibernate.type.descriptor.sql.VarbinaryTypeDescriptor$1.doBind(VarbinaryTypeDescriptor.java:45) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:73) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter$1.bind(AttributeConverterSqlTypeDescriptorAdapter.java:88) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:276) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:271) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:39) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2929) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3226) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3760) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:107) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:na]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1352) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:443) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3202) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2370) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:534) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) ~[spring-tx-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:631) ~[spring-tx-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:385) ~[spring-tx-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) ~[spring-tx-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]

当我不使用转换器直接创建 Point 对象时,它按预期工作。

以下是其他一些相关的项目细节:

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-spatial</artifactId>
            <version>5.3.16.Final</version>
        </dependency>

  jpa:
    database-platform: org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect
4

1 回答 1

0

您的解决方案不适合 GIS 解决方案。我认为您的问题是,您尝试插入表格的几何图形

com.vividsolutions.jts.geom.Geometry

postgis 的类型不对,必须创建;

org.postgis.Point

你的几何必须是;

org.postgis.PGgeometry

写postgis专栏。

如果我是你,我会使用 geotools 库将功能导入 postgis。它有一个 postgis 数据存储。链接在这里:

Geotools Postgis 数据存储

并且有很多示例,如何从数据存储中添加、编辑、删除功能。

Properties params = new Properties();
params.put("user", "postgres");
params.put("passwd", "postgres");
params.put("port", "5432");
params.put("host", "127.0.0.1");
params.put("database", "test");
params.put("dbtype", "postgis");

DataStore dataStore = DataStoreFinder.getDataStore(params);
SimpleFeatureSource source = dataStore.getFeatureSource("tablename");
if (source instanceof SimpleFeatureStore) {
  SimpleFeatureStore store = (SimpleFeatureStore) source;
  store.addFeatures(DataUtilities.collection(features));
} else {
  System.err.println("Unable to write to database");
}

示例代码必须是这样的,我在stackoverflow上找到了它,但我没有测试过。

于 2020-04-29T00:26:30.007 回答