PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come mappare org.postgresql.geometric.PGpoint su Tipo di sospensione

Innanzitutto, penso a GEOMETRY i tipi di dati sono supportati da Hibernate Spatial , ma in caso contrario, puoi sempre definire un tipo di sospensione personalizzato e un dialetto di sospensione personalizzato.

Ho avuto un problema simile durante la gestione di un POINT colonna che conteneva punti geografici.

Ho creato un PostgisDialect classe che ha esteso PostgreSQL9Dialect , dove registri il nuovo tipo di dati in questo modo

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

nel tuo caso, registreresti il ​​tipo come "geometria"

quindi, definisci un GeometryType classe che implementa UserType

Stranamente, il processo di scrittura di un tipo di ibernazione personalizzato non è una delle funzionalità più documentate, quindi incollerò qui ciò che ho scritto per definire il mio PointType. Per gli altri metodi nell'interfaccia, li lascio lanciare 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};
}    

}

alcune brevi note:nullSafeSet e nullSafeGet scrivono e leggono i valori nel/dal database, rispettivamente, utilizzando gli oggetti BinaryWriter/BinaryParser.

Dopo aver definito tutto questo, è così che annoti la tua classe modello in modo che utilizzi il tuo tipo personalizzato

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

Ultimo, ma non meno importante, devi dire a Hibernate di usare il tuo dialetto personalizzato. Se usi Spring per definire la tua sessione factory, puoi definirla tramite hibernateProperties

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