Skip to main content

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

Just one note:
Because of me using postgis instead of vividsolutions the converter class
looks like that:

package de.fhg.fokus.openride.helperclasses.converter;
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 java.util.logging.Logger;
import org.postgis.Point;

/**
 * Eclipselink converter to/from postgis Point / PGPoint
 *
 *
 */
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) {
        System.out.println("PGPopint: "+dataValue);
      return new Point(((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
        // init changed -> should be working!
      return null;
    }
    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 dm, Session session) {
    dm.getField().setSqlType(java.sql.Types.OTHER);
  }


  public boolean isMutable() {
    return false;
  }
}


PS: this is deployed on a glassfishV3 using PostGres8.3+PostGis 1.3.6



Mike Traum-2 wrote:
> 
> I seem to have fixed the null issue.  Change 
> convertObjectValueToDataValue to return null when the value is null and 
> then replace the initialize method with the code below and it seems to
> work.
> 
> mike
> 
>   public void initialize(DatabaseMapping dm, Session session) {
>     dm.getField().setSqlType(java.sql.Types.OTHER);
>   }
> 
> 
> Mike Traum wrote:
>> 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
>>>   
>>
> _______________________________________________
> eclipselink-users mailing list
> eclipselink-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
> 
> 

-- 
View this message in context: http://old.nabble.com/eclipseLink-%2B-PostGIS-datatypes-tp27026862p27143389.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.



Back to the top