我将我的应用程序从spring jdbc迁移到JPA + Hibernate,并且使用的数据库是postgres。如果我使用spring jdbc,DB中的其中一个表的点数据类型转换为org.postgresql.geometric.PGpoint。我不知道如何将它映射到Hibernate类型。有人可以让我知道如何将点数据类型映射到休眠类型。
解决方案首先,我认为 GEOMETRY 数据类型由支持,但如果他们不是,你总是可以定义一个自定义的Hibernate类型和一个自定义的Hibernate方言。
当管理 POINT 包含地理点的列。
我创建了一个扩展 PostgreSQL9Dialect 的 PostgisDialect 类,在这里注册新的数据类型
public PostgisDialect(){ registerColumnType(Types.BINARY,地理); }在这种情况下,您可以将类型注册为geometry
然后,定义一个类,它实现 UserType 奇怪的是,编写自定义Hibernate类型的过程并不是最常见的功能之一,因此我将在此处粘贴我写的用于定义我的PointType的内容。对于接口中的其他方法,我让它们抛出 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; $ b $ public boolean equals(Object o,Object o1)throws HibernateException { if((o instanceof Point&& o1 instanceof Point)== false)返回false; Point p1 =(Point)o; Point p2 =(Point)o1; boolean equal =((p1.getX()== p2.getX())&&(p1.getY()== p2.getY())); 回报相等; $ b public Object nullSafeGet(ResultSet rs,String [] strings,SessionImplementor si,Object o)throws HibernateException,SQLException { //从列中获取数据并使用BinaryParser将其转换为Point的方法 BinaryParser bp = new BinaryParser(); 尝试{ String binaryString = rs.getString(strings [0]); 返回bp.parse(binaryString); } catch(Exception ex){return null;} $ b $ public void nullSafeSet(PreparedStatement ps,Object o,int i,SessionImplementor si)抛出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()); } 返回newPoint; } public boolean isMutable(){ return true; public int [] sqlTypes(){ return new int [] {Types.BINARY}; }}
一些快速注释:nullSafeSet和nullSafeGet分别使用BinaryWriter / BinaryParser对象向/从数据库写入和读取值。
一旦定义了所有这些,是你如何注释你的模型类,以便它使用你的自定义类型
@Column(name =point) @Type(type =eu.enricorampazzosoluzioni.incidentpredicter.dataCopier.hibernate.types.PointType) private point point;最后但并非最不重要的是,您需要告诉Hibernate使用您的自定义方言。如果你使用Spring来定义会话工厂,你可以通过 hibernateProperties
来定义它。 pre $ < property name =hibernateProperties> <道具> < prop key =hibernate.dialect> eu.enricorampazzosoluzioni.incidentpredicter.dataCopier.hibernate.dialect.PostgisDialect< / prop> < /道具> < / property>
I'm migrating my application from spring jdbc to JPA + Hibernate and the DB used is postgres. One of my table in the DB has point data type which translates to org.postgresql.geometric.PGpoint if i use spring jdbc. I don't how to map this to Hibernate type. Can some one please let me know how do I map the point data type to a hibernate type.
解决方案First and foremost, I think GEOMETRY data types are supported by Hibernate Spatial, but if they are not, you can always define a custom Hibernate Type and a custom Hibernate Dialect.
I had a similar problem when managing a POINT column which contained geography points.
I created a PostgisDialect class which extended PostgreSQL9Dialect, where you register the new data type in this way
public PostgisDialect() { registerColumnType(Types.BINARY, "geography"); }in your case, you would register the type as "geometry"
then, you define a GeometryType class which implements UserType
Oddly enough, the process of writing a custom Hibernate Type is not one of the most documented features, so I will paste here what I wrote to define my PointType. For the other methods in the interface, I let them throw 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}; }}
some quick notes: nullSafeSet and nullSafeGet writes and reads the values to/from the database, respectively, using the BinaryWriter/BinaryParser objects.
Once you have defined all this, this is how you annotate your model class so that it uses your custom type
@Column(name="point") @Type(type="eu.enricorampazzosoluzioni.incidentpredicter.dataCopier.hibernate.types.PointType") private Point point;Last, but not least, you need to tell Hibernate to use your custom dialect. If you use Spring to define your session factory, you can define it via hibernateProperties
<property name="hibernateProperties"> <props> <prop key="hibernate.dialect">eu.enricorampazzosoluzioni.incidentpredicter.dataCopier.hibernate.dialect.PostgisDialect</prop> </props> </property>
更多推荐
如何将org.postgresql.geometric.PGpoint映射到Hibernate类型
发布评论