当前位置: 首页 > 知识库问答 >
问题:

Hibernate Spatial和PostGIS的属性转换

郭远
2023-03-14

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

我正在使用Hibernate Sspace al并尝试开发一个属性转换器,以从我的Sspace al位置对象创建预期的Point对象。

空间位置基本上具有坐标信息:

@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);
    }

}

下面是如何在Address类上设置属性:

    @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

共有1个答案

皇甫鸿远
2023-03-14

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

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

 类似资料:
  • 当我在地理专栏中使用st_dwithin和GIST索引时,解释计划显示索引扫描上的缩小条件变为 解释计划中没有索引的条件为 但解释计划表示,当列有GIST索引时,将其更改为以下内容 地理列有一个自定义的空间参照系,在转换为 设置代码如下所示 将st_dwithin距离从3增加到230000将返回所有三个预期行,因为在srid 4326中这是它们的距离。 当列上存在索引时,如何让PostGIS在查询

  • 问题内容: 我想使用JPA 2.0映射来自PostGIS的数据类型。我用谷歌搜索解决方案或示例,但我能找到的是JPA不支持自定义数据类型的映射。在JPA 2.0中还是这样吗?有人暗示一个例子吗? 问题答案: 我用谷歌搜索解决方案或示例,但我能找到的是,JPA不支持自定义数据类型的映射。它仍然在JPA 2.0中吗? 是。因此,您必须依赖特定的扩展。对于Hibernate,Hibernate Spat

  • 属性与Java中的字段是相同的,但是更加强大。属性做的事情是字段加上getter加上setter。我们通过一个例子来比较他们的不同之处。这是Java中字段安全访问和修改所需要的代码: public class Person { private String name; public String getName() { return name; }

  • 由于Python是动态语言,根据类创建的实例可以任意绑定属性。 给实例绑定属性的方法是通过实例变量,或者通过self变量: class Student(object): def __init__(self, name): self.name = name s = Student('Bob') s.score = 90 但是,如果Student类本身需要绑定一个属性呢?可

  • 问题内容: 是否可以某种方式用于属性值,而不是替换内部HTML内容?例如这个简单的指令 并用作 我希望它翻译成 有什么办法吗,还是我必须使用属性而不是包含? 这是 摆弄例子 问题答案: 像这样: 摆弄。

  • 问题内容: 我想将DIV旋转到一定程度。在FF中它可以运行,但是在IE中我面临一个问题。 例如,在以下样式中,我可以将rotation = 1设置为4 这意味着DIV将旋转到90或180或270或360度。但是,如果我只需要将DIV旋转20度,那么它将不再起作用。 如何在IE中解决此问题? 问题答案: 要在IE中旋转45度,您需要在样式表中添加以下代码: 您将从上面的内容中注意到IE8与IE6 /