Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] eclipseLink + PostGIS datatypes

Your converter doesn't do any converting ;). Below is something I came up with pretty quickly. There is one known bug here - it won't store a null properly. I'm guessing PGpoint can be extended to handle that case properly under eclipselink. Also, I can't see a way to set the SRID.

You probably want to use the annotation '@Column(columnDefinition="point")' on the field - it's not necessary, but if you ever generate the schema from eclipselink, it will generate it properly.

If you figure out a solution for the null issues or make any more enhancements, please post them here.

mike


import java.util.logging.Logger;

import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.sessions.Session;
import org.postgresql.geometric.PGpoint;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;

/**
* Eclipselink converter to/from postgis Point
*
* @author Mike Traum
*
*/
public class PointConverter implements Converter {
 private static final long serialVersionUID = -5938037316595234421L;
 static Logger log = Logger.getLogger(PointConverter.class.getName());

public Point convertDataValueToObjectValue(Object dataValue, Session session) {
   if (dataValue == null) {
     return null;
   }
   else if (dataValue instanceof PGpoint) {
     GeometryFactory geomFact = new GeometryFactory();
return geomFact.createPoint(new Coordinate(((PGpoint)dataValue).x, ((PGpoint)dataValue).y));
   }
   else {
     log.severe("dataValue not instance of PGpoint");
     return null;
   }
 }

public PGpoint convertObjectValueToDataValue(Object objectValue, Session session) {
   if (objectValue == null) {
// can't return null here it will attempt to store as varchar - this results in a POINT(0,0), which is incorrect
     return new PGpoint();
   }
   else if (objectValue instanceof Point) {
return new PGpoint(((Point)objectValue).getX(), ((Point)objectValue).getY());
   }
   else {
     log.severe("objectValue not instance of Point");
     return new PGpoint();
   }
 }

public void initialize(DatabaseMapping arg0, Session arg1) { }

 public boolean isMutable() {
   return false;
 }
}



Abromeit, Philipp wrote:
That sounds very interesting. As you distinguished totally right I need to use the datatype Point, because of using some postgis specific functions. I already tried to write a Converter but maybe I did not well understand the concept. What I did so far is:

public class MyConverter implements Converter{
    public Point convertObjectValueToDataValue(Object objectValue, Session session) {
        return (Point) objectValue;
    }

    public Point convertDataValueToObjectValue(Object dataValue, Session session) {
        return (Point)dataValue;
    }

    public boolean isMutable() {
        return false;
    }

    public void initialize(DatabaseMapping mapping, Session session) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }
}

And then integrating it like that:

    @Converter(name="convert", converterClass=MyConverter.class)
public class Test implements Serializable {
    private static final long serialVersionUID = 1L;
    @Column(name = "test")
    @Convert("convert")
    private Point test;

I would now be very interested in your proposals to make this work.

Thanks Philipp

-----Original Message-----
From: eclipselink-users-bounces@xxxxxxxxxxx [mailto:eclipselink-users-bounces@xxxxxxxxxxx] On Behalf Of Mike Traum
Sent: Mittwoch, 6. Januar 2010 16:45
To: EclipseLink User Discussions
Subject: Re: [eclipselink-users] eclipseLink + PostGIS datatypes

It sounds like you have the column in the db defined as type 'point', but without using a Converter, it'll want to store it as bytea. So, I think changing the field to bytea will fix it.

What this is doing is serializing the Geometry object and storing it. It will then deserialize it on retrieval. I think you may want to consider writing a Converter for the column. This way, the field can be used outside of java. And, even within java, you won't be able to use spatial functions with the field in sql. Also, if the Geometry object changes in the future versions of postgres, deserialization may have issues.

Currently, we are storing spatial columns as their EWKT (text) representations, but by doing so it is also more difficult to perform spatial queries. If you do want to write the converter (it should not be that difficult, but there are many postgis types), we can collaborate a bit off list.

mike

Abromeit, Philipp wrote:
If I remove this annotation eclipseLink returns the following:

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: FEHLER: Spalte »test« hat Typ point, aber der Ausdruck hat Typ bytea
Error Code: 0
Call: INSERT INTO test (id, test) VALUES (?, ?)
        bind => [601, [B@1180cbd]
Query: InsertObjectQuery(entity.Test[id=601])

-----Original Message-----
From: eclipselink-users-bounces@xxxxxxxxxxx [mailto:eclipselink-users-bounces@xxxxxxxxxxx] On Behalf Of Guy Pelletier
Sent: Mittwoch, 6. Januar 2010 15:31
To: EclipseLink User Discussions
Subject: Re: [eclipselink-users] eclipseLink + PostGIS datatypes

Try removing the @Convert specification. By specifying this you are saying use no conversion at all.

Cheers,
Guy

----- Original Message ----- From: "Philipp123451" <Philipp.Abromeit@xxxxxxxxxxxxxxxxxxx>
To: <eclipselink-users@xxxxxxxxxxx>
Sent: Wednesday, January 06, 2010 8:47 AM
Subject: [eclipselink-users] eclipseLink + PostGIS datatypes



Hello everybody.
As the topic indicates, I'm trying to use JPA
(eclipselink-2.0.0.v20091127-r5931) with glassfish v3 and PostGres 8.4 with
PostGIS 1.4.1. The Problem is, PostGIS datatypes (e.g. org.postgis.Point) is
converted to type "bytea" during the persistence process. I've found several
blogs saying this should be possible, but for me this seems impossible. For
example:
http://www.naxos-software.de/blog/index.php?/archives/40-PostgreSQLs-geometrische-Datentypen-und-die-Java-Persistence-API.html
. At the bottom of this article someone says, this:
@Entity @Table(name = "route_point") public class RoutePoint implements
Serializable { @Id @GeneratedValue @Column(name = "id", nullable = false)
private Integer id;

@Column(name = "seq_no", nullable = false)
private int seqNo;
@JoinColumn(name = "route", referencedColumName = "id")
@ManyToOne
private Route route;
@Column(name = "geo_point", nullable = false)
@Lob
@Convert
private Geometry pointAsObject;

public RoutePoint() {
}

}

shall be working. I tried but was not successfull. eclipselink returns:

Exception [EclipseLink-4002] (Eclipse Persistence Services -
2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: FEHLER: Spalte »test«
hat Typ point, aber der Ausdruck hat Typ bytea
Error Code: 0
Call: INSERT INTO test (id, test) VALUES (?, ?)
        bind => [601, [B@552da4]
Query: InsertObjectQuery(entity.Test[id=601])

Another way I tried is to implement the "Converter" interface of
eclipseLink. I added to the attribute of type point the following:

@Converter(name="convert", converterClass=MyTypeConverter.class)
public class Test implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name = "test")
    @Convert("convert")
    private Point test;

    @Id
    @Basic(optional = false)
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;
...
}

The implementation of the Converter looks like that:

public class MyTypeConverter implements Converter{
    public Point convertObjectValueToDataValue(Object objectValue, Session
session) {
        return (Point) objectValue;
    }

    public Point convertDataValueToObjectValue(Object dataValue, Session
session) {
        return (Point)dataValue;
    }

    public boolean isMutable() {
        return false;
    }

    public void initialize(DatabaseMapping mapping, Session session) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }
}

eclipseLink now returns:

Exception [EclipseLink-4002] (Eclipse Persistence Services -
2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: Der in SQL für eine
Instanz von org.postgis.Point zu verwendende Datentyp kann nicht abgeleitet
werden. Benutzen Sie 'setObject()' mit einem expliziten Typ, um ihn
festzulegen.
Error Code: 0
Call: INSERT INTO test (id, test) VALUES (?, ?)
        bind => [601, POINT(0 0)]
Query: InsertObjectQuery(entity.Test[id=601])

I don't see the failure. I would be very pleased if someone could tell me
how to solve this problem.

With regards
Philipp
------------------------------------------------------------------------

_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
------------------------------------------------------------------------

_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users


Back to the top