私のPostgreSQL 9.3 + PostGIS 2.1.5では、タイプGeometry(Point,26910)
の列PLACE
を持つテーブルcoordinates
があります。
Hibernate 4.0.0 +を使用するSpring Boot 1.1.9 WebアプリケーションのPlace
エンティティにマッピングしたい。 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" : {
などなど...春のログは役に立ちません。
私はこの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>
少し奇妙な設定、私はインターネットでそれを見つけました、それは今のところ最もうまくいくものです。
誰かがこの謎を助けてくれることを願っています。 :)
最後に、自分の構成に問題がなく、Point
データ型を正しく管理できないJacksonである可能性があることを発見しました。そこで、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;
}
}
}
this serializer および this deserializer を使用することもできます here を使用できます。
このシリアライゼーション/デシリアライゼーションも私にとってはうまくいきました。
上記の解決策は私が問題を解決するのに役立ちました。他の人が理解できるように簡略化します。
このライブラリを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 geomertry;
@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 getGeomertry() {
return geomertry;
}
public void setGeomertry(Geometry geomertry) {
this.geomertry = geomertry;
}
}
私のテーブルには次の2つの列がありました。
id | integer
geometry | geometry(Geometry,4326) |
問題はPostgreSQLに関連しているようには見えません。 POJOに後方参照があるようです。つまり、マッパーはそれを処理する方法を知りません。マッパーがいつ停止するかがわかるように、再帰的な関係を明示的に定義する必要があります。 (私のGotoリンク-> http://vard-lokkur.blogspot.com/2010/10/json-jackson-to-rescue.html )
ポイントを使用しているすべてのフィールドに注釈を追加したくない場合は、@ JsonComponentを使用してJsonSerializerおよびJsonDeserializer。
@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();
}
}