PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

So ordnen Sie org.postgresql.geometric.PGpoint Hibernate Type zu

In erster Linie denke ich an GEOMETRY Datentypen werden von Hibernate Spatial unterstützt , aber wenn dies nicht der Fall ist, können Sie jederzeit einen benutzerdefinierten Hibernate-Typ und einen benutzerdefinierten Hibernate-Dialekt definieren.

Ich hatte ein ähnliches Problem bei der Verwaltung eines POINT Spalte, die geografische Punkte enthielt.

Ich habe einen PostgisDialect erstellt Klasse, die PostgreSQL9Dialect erweitert , wo Sie den neuen Datentyp auf diese Weise registrieren

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

in Ihrem Fall würden Sie den Typ als "Geometrie"

registrieren

dann definieren Sie einen GeometryType Klasse, die UserType implementiert

Seltsamerweise gehört das Schreiben eines benutzerdefinierten Hibernate-Typs nicht zu den am besten dokumentierten Funktionen, daher füge ich hier ein, was ich geschrieben habe, um meinen PointType zu definieren. Für die anderen Methoden in der Schnittstelle lasse ich sie UnsupportedOperationException auslösen

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};
}    

}

Einige kurze Anmerkungen:nullSafeSet und nullSafeGet schreiben bzw. lesen die Werte in die/aus der Datenbank unter Verwendung der BinaryWriter/BinaryParser-Objekte.

Nachdem Sie dies alles definiert haben, kommentieren Sie Ihre Modellklasse folgendermaßen, damit sie Ihren benutzerdefinierten Typ verwendet

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

Zu guter Letzt müssen Sie Hibernate mitteilen, dass es Ihren benutzerdefinierten Dialekt verwenden soll. Wenn Sie Spring verwenden, um Ihre Session-Factory zu definieren, können Sie sie über hibernateProperties definieren

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