prosource

투고 맵핑스프링 부트 시 휴지 상태에서의 GIS 지오메트리 포인트 필드

probook 2023. 2. 27. 22:27
반응형

투고 맵핑스프링 부트 시 휴지 상태에서의 GIS 지오메트리 포인트 필드

내 포스트그레SQL 9.3 + 투고GIS 2.1.5 표가 있다PLACE기둥을 박고coordinates타입의Geometry(Point,26910).

매핑하고 싶다Placespring boot 1.1.9 웹 어플리케이션의 엔티티입니다.이 어플리케이션에서는 휴지 상태 4.0.0 + 를 사용합니다.Place는 REST 저장소와 함께 사용할 수 있습니다.

아쉽게도 제가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" : {

그리고 막무가내로...!봄 일지는 도움이 안 돼요

이 어플리케이션.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;
}

my 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>

조금 이상한 설정입니다.인터넷에서 찾았는데 지금으로서는 그게 가장 잘 작동하는 설정입니다.

이 미스터리를 누가 좀 도와줬으면 좋겠어요.:)

마지막으로 내 구성이 정상이며 관리가 불가능한 Jackson일 수 있음을 알게 되었습니다.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;
    
    public class PointToJsonSerializer extends JsonSerializer<Point> {
    
        @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<Point> {
    
        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;
            }
        }
    
    }
    

시리얼라이저와 디시리얼라이저사용할 수도 있습니다.여기서 구할 수 있습니다.

위의 해결책이 문제를 해결하는 데 도움이 되었습니다.나는 다른 사람들이 이해할 수 있도록 단순화한다.

이 라이브러리를 pom.xml에 포함시켰습니다.

<dependency>
  <groupId>com.bedatadriven</groupId>
  <artifactId>jackson-datatype-jts</artifactId>
  <version>2.2</version>
</dependency>

이것은 제가 사용한 POJO 오브젝트입니다.그리고 봉투 오류와 적절한 좌표 없이 REST 전화를 작동시킬 수 있었습니다.

import com.bedatadriven.jackson.datatype.jts.serialization.GeometryDeserializer;
import com.bedatadriven.jackson.datatype.jts.serialization.GeometrySerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.vividsolutions.jts.geom.Geometry;

@Entity
@Table(name = "boundary")
public class Boundary {

    private int id;
    private Geometry geometry;

    @Id
    public int getId() {
        return ogc_fid;
    }

    public void setId(int id) {
        this.id = id;
    }
    
    @JsonSerialize(using = GeometrySerializer.class)
    @JsonDeserialize(using = GeometryDeserializer.class)
    @Column(name = "geometry", columnDefinition = "Geometry")
    public Geometry getGeometry() {
        return geometry;
    }

    public void setGeometry(Geometry geometry) {
        this.geometry = geometry;
    }
}

테이블에는 다음 두 개의 열이 있습니다.

id       | integer            
geometry | geometry(Geometry,4326) | 

Hibernate 5.4와 Posgis 13+를 사용하면 매우 쉬워졌습니다.최신 휴지 상태-공간 종속성을 추가할 수 있습니다.

    <!-- Hibernate Spatial for storing and retrieving geometries -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-spatial</artifactId>
        <version>${hibernate.version}</version>
    </dependency>

최신 Posgis 사투리를 사용합니다. application.properties를 추가합니다.

spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect

또, 휴지 상태(여기를 참조)에서 서포트되고 있기 때문에, 간단하게 JST 지오메트리를 사용할 수 있습니다.

import org.locationtech.jts.geom.Point;

@Entity(name = "address")
public class Address {
 private Point location;
}

SQL에서 엔티티 테이블을 만듭니다.

CREATE TABLE if not EXISTS address (location geometry);

JTS GeoJSON Reader 및 Writer를 사용하여 지오메트리를 JSON으로 변환할 수 있습니다(여기를 참조).

이 시리얼화/디시리얼화도 문제없이 진행되었습니다.

https://github.com/bedatadriven/jackson-datatype-jts

문제는 Postgre와 관련이 없는 것 같다.SQL입니다. POJO에 백레퍼런스가 있는 것 같습니다. 즉, 매퍼가 어떻게 대처해야 할지 모른다는 뜻입니다.매퍼가 중지할 시기를 알 수 있도록 재귀 관계를 명시적으로 정의해야 합니다.(My Goto link --> http://vard-lokkur.blogspot.com/2010/10/json-jackson-to-rescue.html)

Point를 사용하는 모든 필드에 주석을 추가하지 않으려면 @JsonComponent를 사용하여 JsonSerializerJsonDeserializer를 등록할 수도 있습니다.

@JsonComponent
public class PointSerializer extends JsonSerializer<com.vividsolutions.jts.geom.Point>{

    @Override
 public void serialize(com.vividsolutions.jts.geom.Point value, JsonGenerator gen, SerializerProvider provider) throws IOException {
     gen.writeStartObject();
     gen.writeNumberField("lat", value.getY());
     gen.writeNumberField("lon", value.getX());
     gen.writeEndObject();
 }
}

언급URL : https://stackoverflow.com/questions/27624940/map-a-postgis-geometry-point-field-with-hibernate-on-spring-boot

반응형