sql >> Base de Datos >  >> RDS >> PostgreSQL

Cómo mapear org.postgresql.geometric.PGpoint a Hibernate Type

En primer lugar, creo que GEOMETRY los tipos de datos son compatibles con Hibernate Spatial , pero si no lo son, siempre puede definir un Tipo de Hibernación personalizado y un Dialecto de Hibernación personalizado.

Tuve un problema similar al administrar un POINT columna que contenía puntos de geografía.

Creé un PostgisDialect clase que extendió PostgreSQL9Dialect , donde registras el nuevo tipo de datos de esta manera

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

en su caso, registraría el tipo como "geometría"

luego, defines un GeometryType clase que implementa UserType

Por extraño que parezca, el proceso de escribir un Hibernate Type personalizado no es una de las características más documentadas, así que pegaré aquí lo que escribí para definir mi PointType. Para los otros métodos en la interfaz, los dejo lanzar 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};
}    

algunas notas rápidas:nullSafeSet y nullSafeGet escriben y leen los valores a/desde la base de datos, respectivamente, usando los objetos BinaryWriter/BinaryParser.

Una vez que haya definido todo esto, así es como anota su clase de modelo para que use su tipo personalizado

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

Por último, pero no menos importante, debe decirle a Hibernate que use su dialecto personalizado. Si usa Spring para definir su fábrica de sesiones, puede definirla a través de hibernateProperties

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