使用Hibernate Spatial和PostGIS进行属性转换

问题描述 投票:1回答: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);
    }

}

这里是PointConverter:

@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]

当我不使用Converter直接创建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
spring-boot postgis hibernate-spatial postgresql-12
1个回答
0
投票

您的解决方案不适用于GIS解决方案。我认为您的问题是,您要插入表格的几何形状

com.vividsolutions.jts.geom.Geometry

对于Postgis,它的类型是错误的,所以必须创建;

org.postgis.Point

并且您的几何图形必须是;

org.postgis.PGgeometry

写postgis专栏。

[如果我是您,则使用geotools库将要素导入到Postgis。它有一个postgis数据存储。这是链接:

Geotools Postgis Datastore

还有很多示例,说明如何从数据存储中添加,编辑,删除功能。

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上找到了它,但是我没有进行测试。

© www.soinside.com 2019 - 2024. All rights reserved.