一尘不染

在Spring Boot上使用Hibernate映射PostGIS几何点字段

spring-boot

在我的PostgreSQL 9.3 + PostGIS 2.1.5中,我有一个表PLACE,其列coordinates类型为Geometry(Point,26910)

我想将其映射到 使用Hibernate 4.0.0 +PlaceSpring Boot 1.1.9 Web应用程序中的实体
PlaceREST存储库中可用。

不幸的是,当我GET http://localhost:8080/mywebapp/places收到
这个奇怪的JSON响应时:

{

  "_embedded" : {

    "venues" : [ {

      "id" : 1,

      "coordinates" : {

        "envelope" : {

          "envelope" : {

            "envelope" : {

              "envelope" : {

                "envelope" : {

                  "envelope" : {

                    "envelope" : {

                      "envelope" : {

                        "envelope" : {

                          "envelope" : {

                            "envelope" : {

                              "envelope" : {

                                "envelope" : {

                                  "envelope" : {

                                    "envelope" : {

                                      "envelope" : {

                                        "envelope" : {

                                          "envelope" : {

                                            "envelope" : {

等等等等……!Spring日志没有帮助..

我正在使用此application.properties:

spring.jpa.database-platform=org.hibernate.spatial.dialect.postgis.PostgisDialect
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=update

spring.datasource.url=jdbc:postgresql://192.168.1.123/mywebapp
spring.datasource.username=postgres
spring.datasource.password=mypwd
spring.datasource.driverClassName=org.postgresql.Driver

首先,可以使用database-platform代替database吗?而也许我必须使用以下设置,而不是上面?

spring.datasource.url=jdbc:postgresql_postGIS://192.168.1.123/mywebapp
spring.datasource.driverClassName=org.postgis.DriverWrapper

无论如何,我的实体是这样的:

@Entity
public class Place {
    @Id
    public int id;
    @Column(columnDefinition="Geometry")
    @Type(type="org.hibernate.spatial.GeometryType")    //"org.hibernatespatial.GeometryUserType" seems to be for older versions of Hibernate Spatial
    public com.vividsolutions.jts.geom.Point coordinates;
}

我的pom.xml包含以下相关部分:

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>9.3-1102-jdbc41</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-spatial</artifactId>
    <version>4.3</version><!-- compatible with Hibernate 4.3.x -->
    <exclusions>
        <exclusion>
            <artifactId>postgresql</artifactId>
            <groupId>postgresql</groupId>
        </exclusion>
    </exclusions>
</dependency>

有点奇怪的配置,我在互联网上找到了,它是目前最有效的配置。

我希望有人可以帮助我解决这个问题。:)


阅读 945

收藏
2020-05-30

共1个答案

一尘不染

最后,我发现我的配置是OK,可能是杰克逊是无法管理Point正确的数据类型。因此,我自定义了其JSON序列化和反序列化:

  • 将这些注释添加到我们的coordinates字段中:

    @JsonSerialize(using = PointToJsonSerializer.class)
    

    @JsonDeserialize(using = JsonToPointDeserializer.class)

  • 创建这样的序列化器:

    import java.io.IOException;
    

    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializerProvider;
    import com.vividsolutions.jts.geom.Point;

    公共类PointToJsonSerializer扩展了JsonSerializer [HTML_REMOVED] {

    @Override
    public void serialize(Point value, JsonGenerator jgen,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {
    
        String jsonValue = "null";
        try
        {
            if(value != null) {             
                double lat = value.getY();
                double lon = value.getX();
                jsonValue = String.format("POINT (%s %s)", lat, lon);
            }
        }
        catch(Exception e) {}
    
        jgen.writeString(jsonValue);
    }
    

    }

  • 创建这样的反序列化器:

    import java.io.IOException;
    

    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.JsonDeserializer;
    import com.vividsolutions.jts.geom.Coordinate;
    import com.vividsolutions.jts.geom.GeometryFactory;
    import com.vividsolutions.jts.geom.Point;
    import com.vividsolutions.jts.geom.PrecisionModel;

    public class JsonToPointDeserializer extends JsonDeserializer {

    private final static GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 26910);
    
    @Override
    public Point deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
    
        try {
            String text = jp.getText();
            if(text == null || text.length() <= 0)
                return null;
    
            String[] coordinates = text.replaceFirst("POINT ?\\(", "").replaceFirst("\\)", "").split(" ");
            double lat = Double.parseDouble(coordinates[0]);
            double lon = Double.parseDouble(coordinates[1]);
    
            Point point = geometryFactory.createPoint(new Coordinate(lat, lon));
            return point;
        }
        catch(Exception e){
            return null;
        }
    }
    

    }

Maybe you can also use this
serializer
and this
deserializer
, available
here.

2020-05-30