PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como mapear org.postgresql.geometric.PGpoint para o tipo de hibernação


Em primeiro lugar, acho que GEOMETRY tipos de dados são suportados pelo Hibernate Spatial , mas se não forem, você sempre pode definir um tipo de hibernação personalizado e um dialeto de hibernação personalizado.

Eu tive um problema semelhante ao gerenciar um POINT coluna que continha pontos geográficos.

Eu criei um PostgisDialect classe que estendeu PostgreSQL9Dialect , onde você registra o novo tipo de dados dessa maneira
public PostgisDialect() {
    registerColumnType(Types.BINARY, "geography");        
}

no seu caso, você registraria o tipo como "geometria"

então, você define um GeometryType classe que implementa UserType

Curiosamente, o processo de escrever um Hibernate Type personalizado não é um dos recursos mais documentados, então vou colar aqui o que escrevi para definir meu PointType. Para os outros métodos na interface, deixo-os lançar 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};
}    

}

algumas notas rápidas:nullSafeSet e nullSafeGet grava e lê os valores de/para o banco de dados, respectivamente, usando os objetos BinaryWriter/BinaryParser.

Depois de definir tudo isso, é assim que você anota sua classe de modelo para que ela use seu tipo personalizado
@Column(name="point")
@Type(type="eu.enricorampazzosoluzioni.incidentpredicter.dataCopier.hibernate.types.PointType")
private Point point;

Por último, mas não menos importante, você precisa dizer ao Hibernate para usar seu dialeto personalizado. Se você usa Spring para definir sua fábrica de sessões, você pode defini-la via hibernateProperties
<property name="hibernateProperties">
     <props>           
         <prop key="hibernate.dialect">eu.enricorampazzosoluzioni.incidentpredicter.dataCopier.hibernate.dialect.PostgisDialect</prop>            
     </props>
  </property>