PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment mapper org.postgresql.geometric.PGpoint au type Hibernate

D'abord et avant tout, je pense GEOMETRY les types de données sont pris en charge par Hibernate Spatial , mais s'ils ne le sont pas, vous pouvez toujours définir un type d'hibernation personnalisé et un dialecte d'hibernation personnalisé.

J'ai eu un problème similaire lors de la gestion d'un POINT colonne contenant des points géographiques.

J'ai créé un PostgisDialect classe qui étend PostgreSQL9Dialect , où vous enregistrez le nouveau type de données de cette manière

public PostgisDialect() {
    registerColumnType(Types.BINARY, "geography");        
}

dans votre cas, vous enregistreriez le type comme "géométrie"

ensuite, vous définissez un GeometryType classe qui implémente UserType

Curieusement, le processus d'écriture d'un type Hibernate personnalisé n'est pas l'une des fonctionnalités les plus documentées, je vais donc coller ici ce que j'ai écrit pour définir mon PointType. Pour les autres méthodes de l'interface, je les laisse lever UnsupportedOperationException

public class PointType implements UserType{
private static final Type[] PROPERTY_TYPES = new Type[] { 
    StringType.INSTANCE };
public String[] getPropertyNames() {
     return new String[] {"point"};   }

public Type[] getPropertyTypes() {
    return PROPERTY_TYPES;
}


public Class returnedClass() {
   return Point.class;
}

public boolean equals(Object o, Object o1) throws HibernateException {
    if((o instanceof Point && o1 instanceof Point) == false)
        return false;
    Point p1 = (Point) o;
    Point p2 = (Point) o1;
    boolean equal = ((p1.getX() == p2.getX()) && (p1.getY() == p2.getY()));
    return equal;


}   

public Object nullSafeGet(ResultSet rs, String[] strings, SessionImplementor si, Object o) throws HibernateException, SQLException {
// the method which gets the data from the column and converts it to a Point using       BinaryParser
   BinaryParser bp = new BinaryParser();       
   try{          
      String binaryString = rs.getString(strings[0]);
       return bp.parse(binaryString);
   }
   catch(Exception ex){ return null;}

}

public void nullSafeSet(PreparedStatement ps, Object o, int i, SessionImplementor si) throws HibernateException, SQLException {
    Point p = (Point) o ;
    if(p!=null){
       BinaryWriter bw = new BinaryWriter();
       ps.setObject(i,bw.writeBinary(p));      
    }

public Object deepCopy(Object o) throws HibernateException {
    Point p = (Point) o;        
    Point newPoint = null;
    if(p!=null){
        newPoint = new Point(p.x, p.y);
        newPoint.setSrid(p.getSrid());
    }
    return newPoint;

}

public boolean isMutable() {
    return true;
}


public int[] sqlTypes() {
    return new int[]{Types.BINARY};
}    

}

quelques notes rapides :nullSafeSet et nullSafeGet écrivent et lisent les valeurs vers/depuis la base de données, respectivement, à l'aide des objets BinaryWriter/BinaryParser.

Une fois que vous avez défini tout cela, voici comment vous annotez votre classe de modèle afin qu'elle utilise votre type personnalisé

@Column(name="point")
@Type(type="eu.enricorampazzosoluzioni.incidentpredicter.dataCopier.hibernate.types.PointType")
private Point point;

Enfin, vous devez indiquer à Hibernate d'utiliser votre dialecte personnalisé. Si vous utilisez Spring pour définir votre usine de session, vous pouvez la définir via hibernateProperties

<property name="hibernateProperties">
     <props>           
         <prop key="hibernate.dialect">eu.enricorampazzosoluzioni.incidentpredicter.dataCopier.hibernate.dialect.PostgisDialect</prop>            
     </props>
  </property>