PostGIS整合Hibernate4.0+Spring(Maven,Kepler)

PostGIS整合Hibernate4.0+Spring(Maven,Kepler)

 

这里我主要讲实际操作和环境的搭配,一些基本概念,请查看维基百科和百度百科。

 

一 PostGIS基本概念:

PostGIS是对象关系型数据库系统PostgreSQL的一个扩展,PostGIS提供如下空间信息服务功能:空间对象、空间索引、空间操作函数和空间操作符。同时,PostGIS遵循OpenGIS的规范。

二 使用的地方:比如查询方圆5公里以内的商店,比如两个城市间的距离等这些跟空间操作有关的功能。

 

三postGIS的安装:

这里我以postgres9.3版本为蓝图讲解下基本的安装。

1 如果你是已经安装好postgres9.3数据库,而需要额外加载postGIS,请去postGIS官网下载

http://postgis.net/install/

 

2 WINDOW请选择Windows Downloads这个选项,进入下载页面,选择相应版本下载安装。

 

3 安装完成后,会在你的数据库拓展里面看到postgis,posgis_topology等跟postgis有关的拓展。

 

4 选择postgis建立拓展。

这样基本的安装就完成了,在插件里面,会发现多了一个PostGIS Shapefile and DBF loader 2.1的插件。

 

 

 

 

 

 而在数据库表中也会多一张叫spatial_ref_sys的表,这个表中包含基本的坐标系的空间信息。

至此,基本的postGIS已经安装成功了。如果有相关疑问或者失败的情况,请参考官方文档:

http://www.bostongis.com/PrinterFriendly.aspx?content_name=postgis_tut01

里面介绍的很详细。

接下来是自己建立测试数据表,用于测试。我截取一部分从官放快速开发的内容,其他请参阅官方文档。

http://live.osgeo.org/zh/quickstart/postgis_quickstart.html

四 手工建立空间数据表格

  空间数据库已经建立,现在可以建立具有空间信息的表格。

  首先建立一个常规的表格存储有关城市(cities)的信息。这个表格有两栏,一个是 ID 编号,一个是城市名:

demo=# CREATE TABLE cities ( id int4, name varchar(50));

  现在添加一个空间栏用于存储城市的位置。习惯上这个栏目叫做 the_geom 。它记录了数据为什么类型(点、线、面)、有几维(这里是二维)以及空间坐标系统。此处使用 EPSG:4326 坐标系统:

demo=# SELECT AddGeometryColumn (‘cities’, ‘the_geom’,4326, ‘POINT’, 2);

  完成后,查询 cities 表单应当显示这个新栏目。同时页面将显示当前表达没有记录(0 rows)。

demo=# SELECT * from cities;

 id | name |the_geom

—-+——+———-

(0 rows)

  为添加记录,需要使用 SQL 命令。对于空间栏,使用 PostGIS 的 ST_GeomFromText 可以将文本转化为坐标与参考系号的记录:

demo=# INSERT INTO cities (id, the_geom, name) VALUES(1,ST_GeomFromText(‘POINT(-0.1257 51.508)’,4326),’London, England’);

demo=# INSERT INTO cities (id, the_geom, name) VALUES(2,ST_GeomFromText(‘POINT(-81.233 42.983)’,4326),’London, Ontario’);

demo=# INSERT INTO cities (id, the_geom, name) VALUES(3,ST_GeomFromText(‘POINT(27.91162491 -33.01529)’,4326),’East London,SA’);

  当然,这样的输入方式难以操作。其它方式可以更快的输入数据。就目前来说,表格内已经有了一些城市数据,可以先进行查询等操作。

PS:你也可以在你已经存在的表中添加空间坐标字段,添加语句如下:

 

SELECT AddGeometryColumn ('cities', 'the_geom', 4326, 'POINT', 2);

 

第一个参数是你要添加的表名,第二个是表中你要添加的字段名称,第三个是SRID信息,之后是空间数据类型,是POINT还是其他。这些在官方文档都有API,请自行查阅。

 

 

至此,数据的安装和测试表的建立都已经完成。开始主要部分,环境的搭建和测试。正好也在熟悉下MAVEN搭建hibernate和Spring.

 

五 Maven搭建hibernate项目。

首先我单独讲,怎么用maven搭建hibernate项目,不使用spring.循序渐进才能知其然也知其所以然。

这里构建hibernate项目会和普通的hibernate项目有所不同,需要添加很多额外的JAR包用于支持postGIS的操作。

 

至于怎么用manven建立web项目,其实有很多技术同志已经写的很好,并且很详细。这里我推荐两个我实践过的。大家自己去看。

http://blog.csdn.net/clj198606061111/article/details/20221133

http://blog.csdn.net/yuguiyang1990/article/details/8796726

 

建立好的基本web项目,pom配置如下:

<projectxmlns=“http://maven.apache.org/POM/4.0.0”xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”

  xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd”>

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.esiee.postGis</groupId>

  <artifactId>postGis</artifactId>

  <packaging>war</packaging>

  <version>0.0.1-SNAPSHOT</version>

  <name>postGis Maven Webapp</name>

  <url>http://maven.apache.org</url>

  <dependencies>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <version>4.11</version>

      <scope>test</scope>

    </dependency>

    <dependency>

            <groupId>javax.servlet</groupId>

            <artifactId>servlet-api</artifactId>

            <version>2.3</version>

            <scope>provided</scope>

   </dependency>

   <dependency>

            <groupId>log4j</groupId>

            <artifactId>log4j</artifactId>

            <version>1.2.17</version>

   </dependency>

  </dependencies>

  <build>

    <finalName>postGis</finalName>

    <plugins>

            <plugin>

                <artifactId>maven-compiler-plugin</artifactId>

                <configuration>

                    <source>1.6</source>

                    <target>1.6</target>

                </configuration>

            </plugin>

            <plugin>

                <groupId>org.codehaus.mojo</groupId>

                <artifactId>tomcat-maven-plugin</artifactId>

                <configuration>

                    <warFile>target/postGis.war</warFile>

                </configuration>

            </plugin>

  </plugins>

  </build>

 

</project>

 

基本目录格式如下:

 

 

现在我们开始进行支持postGIS的Hibernate的配置,Hbiernate要能支持postGIS,需要用到以下几个工具的帮助。

JTS,Hibernate-Spatial, postgis-jdbc

我的版本如下:

  • hibernate-spatial 4.0
  • PostGIS JDBC 1.3.3
  • postgresql-9.3-1100-jdbc41
  • Hibernate 4.2.13.Final
  • JTS 1.8

 

 

首先在pom.xml中加入版本控制信息

 <properties>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <hibernate.version>4.2.13.Final</hibernate.version>

        <maven.tomcat.port>8088</maven.tomcat.port>

  </properties>

 

这里,我们使用4.2.13版本,因为4.3版本有BUG,不能支持Hibernate-Spatial,具体BUG文档,请参阅:

https://hibernate.atlassian.net/browse/HSEARCH-1386

 

现在开始配置:

首先基本的hibernate配置文件如下:

        <dependency>

            <groupId>org.hibernate</groupId>

            <artifactId>hibernate-core</artifactId>

            <version>${hibernate.version}</version>

        </dependency>

 

 

  • postgresql-9.3-1100-jdbc41

        <dependency>

            <groupId>org.postgresql</groupId>

            <artifactId>postgresql</artifactId>

            <version>9.3-1100-jdbc41</version>

        </dependency>

 

  • JTS 1.8

  <dependency>

            <groupId>com.vividsolutions</groupId>

            <artifactId>jts</artifactId>

            <version>1.8</version>

   </dependency>

  • PostGIS JDBC 1.3.3

  <dependency>

            <groupId>org.postgis</groupId>

            <artifactId>postgis-jdbc</artifactId>

            <version>1.3.3</version>

   </dependency>

  • hibernate-spatial 4.0

由于hibernate官方打算以后把spatial导入到未来的新版本5.0中,所以在maven仓库上是找不到该JAR包的,需要单独添加一个repositories属性文件,指定下载地址。

<repositories>

            <repository>

                    <id>OSGEO GeoTools repo</id>

                    <url>http://download.osgeo.org/webdav/geotools</url>

            </repository>

            <repository>

                    <id>Hibernate Spatial repo</id>

                    <url>http://www.hibernatespatial.org/repository</url>

            </repository>

 

</repositories>

 

        <!– Hibernate Spatial –>

        <dependency>

            <groupId>org.hibernate</groupId>

            <artifactId>hibernate-spatial</artifactId>

            <version>4.0</version>

        </dependency>

 

这样基本配置就完成了。

完成的pom.xml如下:

<projectxmlns=“http://maven.apache.org/POM/4.0.0”xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”

  xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd”>

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.esiee.postGis</groupId>

  <artifactId>postGis</artifactId>

  <packaging>war</packaging>

  <version>0.0.1-SNAPSHOT</version>

  <name>postGis Maven Webapp</name>

  <url>http://maven.apache.org</url>

  <properties>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <hibernate.version>4.2.13.Final</hibernate.version>

        <maven.tomcat.port>8088</maven.tomcat.port>

  </properties>

  <repositories>

            <repository>

                    <id>OSGEO GeoTools repo</id>

                    <url>http://download.osgeo.org/webdav/geotools</url>

            </repository>

            <repository>

                    <id>Hibernate Spatial repo</id>

                    <url>http://www.hibernatespatial.org/repository</url>

            </repository>

 

  </repositories>

  <dependencies>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <version>4.11</version>

      <scope>test</scope>

    </dependency>

    <dependency>

            <groupId>javax.servlet</groupId>

            <artifactId>servlet-api</artifactId>

            <version>2.3</version>

            <scope>provided</scope>

   </dependency>

   <dependency>

            <groupId>log4j</groupId>

            <artifactId>log4j</artifactId>

            <version>1.2.17</version>

   </dependency>

   <dependency>

            <groupId>org.hibernate</groupId>

            <artifactId>hibernate-core</artifactId>

            <version>${hibernate.version}</version>

   </dependency>

   <dependency>

            <groupId>org.postgresql</groupId>

            <artifactId>postgresql</artifactId>

            <version>9.3-1100-jdbc41</version>

   </dependency>

   <dependency>

            <groupId>com.vividsolutions</groupId>

            <artifactId>jts</artifactId>

            <version>1.8</version>

   </dependency>

   <dependency>

            <groupId>org.postgis</groupId>

            <artifactId>postgis-jdbc</artifactId>

            <version>1.3.3</version>

   </dependency>

                   <!– Hibernate Spatial –>

   <dependency>

            <groupId>org.hibernate</groupId>

            <artifactId>hibernate-spatial</artifactId>

            <version>4.0</version>

  </dependency>

  </dependencies>

  <build>

    <finalName>postGis</finalName>

    <plugins>

            <plugin>

                <artifactId>maven-compiler-plugin</artifactId>

                <configuration>

                    <source>1.6</source>

                    <target>1.6</target>

                </configuration>

            </plugin>

            <plugin>

                <groupId>org.codehaus.mojo</groupId>

                <artifactId>tomcat-maven-plugin</artifactId>

                <configuration>

                    <warFile>target/postGis.war</warFile>

                </configuration>

            </plugin>

  </plugins>

  </build>

 

</project>

 

 

可以参阅如下文档

http://www.hibernatespatial.org/documentation/documentation/

 

项目列表如下:

 

之后,建立hibernate的cfg文件和mapping文件,这里我全程用的是hibernateTools生成的,这个工作请大家自行用自己的方法完成。

这里要注意的一个事项:我们要使用支持空间操作的方言,故而要加入如下语句:

<propertyname=”hibernate.dialect”>org.hibernate.spatial.dialect.postgis.PostgisDialect</property>

 

Hibernate.cfg.xml

<?xmlversion=“1.0”encoding=“utf-8”?>

<!DOCTYPEhibernate-configuration
PUBLIC

“-//Hibernate/Hibernate Configuration DTD 3.0//EN”

“http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd”>

<hibernate-configuration>

    <session-factory>

        <propertyname=“hibernate.bytecode.use_reflection_optimizer”>false</property>

        <propertyname=“hibernate.connection.driver_class”>org.postgresql.Driver</property>

        <propertyname=“hibernate.connection.password”>test</property>

        <propertyname=“hibernate.connection.url”>jdbc:postgresql://localhost:5432/postgres</property>

        <propertyname=“hibernate.connection.username”>postgres</property>

        <propertyname=“hibernate.dialect”>org.hibernate.spatial.dialect.postgis.PostgisDialect</property>

        <propertyname=“hibernate.search.autoregister_listeners”>false</property>

        <propertyname=“hibernate.show_sql”>true</property>

        <propertyname=“hibernate.format_sql”>true</property>

        <mappingresource=“Cities.hbm.xml”/>

    </session-factory>

</hibernate-configuration>

 

 

Cities.hbm.xml

这里的配置文件,唯一要注意的是将type转换为org.hibernate.spatial.GeometryType用于支持你的空间格式的数据字段。

<?xmlversion=“1.0”?>

<!DOCTYPEhibernate-mapping
PUBLIC“-//Hibernate/Hibernate Mapping DTD 3.0//EN”

“http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd”>

<!– Generated 2014-6-13 14:02:49 by Hibernate Tools 4.0.0 –>

<hibernate-mapping>

    <classname=“Cities”table=“cities”schema=“public”>

        <idname=“id”type=“int”>

            <columnname=“id”/>

            <generatorclass=“assigned”/>

        </id>

        <propertyname=“name”type=“string”>

            <columnname=“name”length=“50”/>

        </property>

        <propertyname=“theGeom”type=“org.hibernate.spatial.GeometryType”>

            <columnname=“the_geom”/>

        </property>

    </class>

</hibernate-mapping>

 

Cities.java类要注意的地方,privateGeometry
theGeom;字段调用

importcom.vividsolutions.jts.geom.Geometry;用于和hiernate配置文件中的TYPE对应。

 

 

import java.io.Serializable;

 

importcom.vividsolutions.jts.geom.Geometry;

 

/**

 * Cities generated by hbm2java

 */

publicclassCities
implements java.io.Serializable {

 

    privateintid;

    private Stringname;

   

    //@Type(type=”org.hibernate.spatial.GeometryType”)

    privateGeometry
theGeom;

 

    public Cities() {

    }

 

    public Cities(int id) {

        this.id = id;

    }

 

    public Cities(int id, String name,Geometry
theGeom) {

        this.id = id;

        this.name = name;

        this.theGeom = theGeom;

    }

 

    publicint getId() {

        returnthis.id;

    }

 

    publicvoid setId(int
id) {

        this.id = id;

    }

 

    public String getName() {

        returnthis.name;

    }

 

    publicvoid setName(String name) {

        this.name = name;

    }

 

    public Serializable getTheGeom() {

        returnthis.theGeom;

    }

 

    publicvoid setTheGeom(Geometry theGeom) {

        this.theGeom = theGeom;

    }

 

}

 

至此,所有的初始工作都做完了。现在可以开始写DAO来测试是否可以进行操作了。

本来想建立基本的DAO模型,增删改查通用,其他操作分开。不过这些工作不是我们的主要目的,故而忽略。只是依然习惯建立DAO接口和DAO实现类,然后写测试方法。

为了测试方便,编写HibernateUtils用于获得hibernate的Session和数据连接。

HibernateUtils.java

package com.esiee.postGis;

 

import org.hibernate.SessionFactory;

import org.hibernate.cfg.AnnotationConfiguration;

 

public class HibernateUtils {

 

    private static final SessionFactory sessionFactory;

   

    static {

        try {

            // Create the SessionFactory from standard (hibernate.cfg.xml)

            // config file.

            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();

        } catch (Throwable ex) {

            // Log the exception.

            System.err.println(“Initial SessionFactory creation failed.” + ex);

            throw new ExceptionInInitializerError(ex);

        }

    }

   

    public static SessionFactory getSessionFactory() {

        return sessionFactory;

    }

 

}

 

ICitiesDAO.java接口中的方法

package com.esiee.postGis;

 

import java.util.List;

 

import com.vividsolutions.jts.geom.Geometry;

 

public interface ICitiesDAO {

 

    /**

     * try the method of HQL

     * @param id

     * @return

     */

    public Cities findByIdHQL(int id);

   

    /**

     * try the method of distance

     * @return

     */

    public List<Cities> showDistance(Geometry geom,double distance);

   

    /**

     * try the method by SpatialRestrictions

     * @return

     */

    public Cities findByFilter(Geometry geom);

   

    /**

     * try use default method

     * @param id

     * @return

     */

    Cities findById(Integer id);

   

    /**

     * try save

     * @param c

     */

    void save(Cities c);

}

 

CitiesDAO.java

package com.esiee.postGis;

 

import java.util.List;

 

import org.hibernate.Criteria;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.spatial.criterion.SpatialRestrictions;

 

import com.vividsolutions.jts.geom.Geometry;

 

publicclass CitiesDAOimplements ICitiesDAO{

 

    @Override

    public Cities findByIdHQL(int id) {

        Session s = HibernateUtils.getSessionFactory().openSession();

        Query q = s.createQuery(“from Cities where id = ?”);

        q.setInteger(0, id);

        return (Cities) q.uniqueResult();

    }

 

    @Override

    public List<Cities> showDistance(Geometry geom,double
distance) {

        Session s = HibernateUtils.getSessionFactory().openSession();

        Criteria c = s.createCriteria(Cities.class);

        c.add(SpatialRestrictions.distanceWithin(“theGeom”, geom, distance));

        return(List<Cities>) c.list();

    }

 

    @Override

    public Cities findByFilter(Geometry geom) {

        Session s = HibernateUtils.getSessionFactory().openSession();

        Criteria c = s.createCriteria(Cities.class);

        //c.add(SpatialRestrictions.distanceWithin(propertyName, geometry, distance));

        c.add(SpatialRestrictions.intersects(“theGeom”, geom));

        return (Cities) c.uniqueResult();

    }

 

    @Override

    public Cities findById(Integer id) {

        Session s = HibernateUtils.getSessionFactory().openSession();

        Cities c = (Cities) s.get(Cities.class, id);

        return c;

    }

 

    @Override

    publicvoid save(Cities c) {

        Session s = HibernateUtils.getSessionFactory().openSession();

        s.beginTransaction();

        s.persist(c);

        s.getTransaction().commit();

       
}

 

}

 

 

 

好,现在开始写测试类,建立Junit 4的测试方法。选择你要测试的类,右键就能选择建立Junit4的测试方法了。

 

 

CitiesDAOTest.java

package com.esiee.postGis;

 

importstatic org.junit.Assert.*;

 

import java.util.List;

 

import org.junit.Before;

import org.junit.Test;

 

import com.vividsolutions.jts.geom.Geometry;

import com.vividsolutions.jts.geom.Point;

import com.vividsolutions.jts.io.ParseException;

import com.vividsolutions.jts.io.WKTReader;

 

publicclass CitiesDAOTest {

 

    ICitiesDAO
ciDao
;

    @Before

    publicvoid setUp()throws
Exception {

        ciDao =new CitiesDAO();

    }

 

    @Test

    publicvoid testFindByIdHQL() {

        fail(“Not yet implemented”);

    }

 

    @Test

    publicvoid testShowDistance() {

        Geometry centerPoint = createPoint(“-16.2564083434446”,“-34.8982159791812”); 

        centerPoint.setSRID(4326);

        //find thepalce near the centrePoint in 5000
kilometres.

        List<Cities> listC =
ciDao
.showDistance(centerPoint, 5000*1000*1/1852*1/60);

        for(Cities c: listC){

            System.out.println(c.getName());

        }

       

    }

 

    @Test

    publicvoid testFindByFilter() {

          Geometry centerPoint = createPoint(“-56.2564083434446”,“-34.8982159791812”); 

          centerPoint.setSRID(4326); 

          Cities cities =
ciDao
.findByFilter(centerPoint);

          System.out.println(“name is “+cities.getName());

        }

 

    @Test

    publicvoid testFindById() {

 

        Cities cities =
ciDao
.findById(1);

        Geometry geom2 = (Geometry) cities.getTheGeom();

        Cities cities2 =
ciDao
.findById(2);

        Geometry geom3 = (Geometry) cities2.getTheGeom();

       

        System.out.println(cities.getName());

        System.out.println(geom2.toString());

        System.out.println(geom2.distance(geom3));

        System.out.println(“type:” + geom2.getGeometryType());

 

    }

   

    @Test

    publicvoid testSave(){

        Geometry centerPoint = createPoint(“-56.2564083434446”,“-34.8982159791812”);

        centerPoint.setSRID(4326);

        Cities cities =
new
Cities(4,“changsha”, centerPoint);

        ciDao.save(cities);

    }

 

    public Point createPoint(String lon,String lat){   

        String wktPoint =
“POINT(“
+ lon +” “+ lat+“)”

        WKTReader fromText =
new
WKTReader(); 

        Geometry geom =
null

        try

            geom = fromText.read(wktPoint); 

        } catch (ParseException e) { 

            thrownew RuntimeException(“Not a WKT string:”
+ wktPoint); 

       

        if (!geom.getGeometryType().equals(“Point”)) { 

            thrownew RuntimeException(“Geometry must be a point.
Got a “
+ geom.getGeometryType()); 

       

        return (Point)geom;   

    }   

}

 

 

首先我们拿testFindById进行基本的测试。测试结果如下:

可以看到,拿到了这个城市的坐标和类型,以及城市名称。

 

这里,我选取几个关键方法进行测试,其他方法,请大家自行测试。

首先是如何保存空间类型的数据对象。这里,关键是处理Geometry这个数据类型。

这个数据类型遵循WKT标准,所以我们需要自己建立一个方法,来处理这个数据,使得我们能将普通的经纬度转为Geometry类型。基本方法如下:

 

public Point createPoint(String lon,String lat){   

        String wktPoint =
“POINT(“
+lon +” “+lat+“)”

        WKTReader fromText =
new
WKTReader(); 

        Geometry geom =null

        try

            geom =fromText.read(wktPoint); 

        } catch (ParseException e) { 

            thrownew RuntimeException(“Not a WKTstring:”
+ wktPoint); 

       

        if (!geom.getGeometryType().equals(“Point”)){ 

            thrownew RuntimeException(“Geometry must bea point.
Got a “
+geom.getGeometryType()); 

       

        return (Point)geom;   

}   

 

之后,我们就可以创建一个坐标系,并加入到数据库。

   @Test

   publicvoidtestSave(){

        Geometry centerPoint = createPoint(“-156.2564083434446”,“-234.8982159791812”);

        centerPoint.setSRID(4326);

        Cities cities =
new
Cities(5,“shanghai”,centerPoint);

        ciDao.save(cities);

}

这里别忘了设置SRIDID,一般为4326,请保持与你数据库中设置的SRID一致,否则会报错。类似于:

org.postgresql.util.PSQLException:错误: Operation on mixed SRID geometries

org.postgresql.util.PSQLException:错误: Geometry SRID (0) does not match column SRID (4326)

至于这个SRID的用途,叫空间引用标识符(SRID),具体用途,请自行维基百科。

 

 

测试方圆500公里内的城市点,这个比较实用。

    @Test

    publicvoid testShowDistance() {

        Geometry centerPoint = createPoint(“-16.2564083434446”,“-34.8982159791812”); 

        centerPoint.setSRID(4326);

        //find thepalce near the centrePoint in 5000
kilometres.

        List<Cities> listC =
ciDao
.showDistance(centerPoint,5000*1000*1/1852*1/60);

        for(Cities c: listC){

            System.out.println(c.getName());

        }

       

}

 

在具体的DAO类中,我使用了Hibernate SpatialRestrictions提供的API

SpatialRestrictions.distanceWithin(“theGeom”,geom, distance)

这样好处是,你可以像写对象操作一样来实现SQL语句。不过这个API提供的方法并不多,复杂的还是可能需要用到HQL或者SQL来实现。有兴趣的,可以深入。

Session s = HibernateUtils.getSessionFactory().openSession();

        Criteria c = s.createCriteria(Cities.class);

        c.add(SpatialRestrictions.distanceWithin(“theGeom”,geom, distance));

 

注意这里的参数中,第三个参数,如果单纯的填写15,200这样的数字,不是具体的距离单位,而是地理坐标系的度数。因此我们需要进行转换。因此500公里的显示方式如下:5000*1000*1/1852*1/60

而在具体的数据中,查询语句如下:

查询距离

     select

       this_.id as id1_6_0_,

       this_.name as name2_6_0_,

        ST_AsEwkt(this_.the_geom),

       ST_Distance_Sphere(this_.the_geom,ST_GeomFromText(‘POINT(-16.2564083434446-34.8982159791812)’,4326))

    from

       public.cities this_

    where

        ST_DWithin(this_.the_geom,ST_GeomFromText(‘POINT(-16.2564083434446-34.8982159791812)’,4326),5000*1000*1/1852*1/60)

 

 

距离它的单位为空间数据单位(度),在运算时需要进行单位换算,最后转换成度

,单位的换算关系如下:

1英里= 63360 米

1米=1/1852 海里

1海里= 1/60度

如果要进行具体的运算,需要进行一下单位换算,比如要求一个500米的范围,那么应该是500*1/1852*1/60(度)

源文档 <http://blog.csdn.net/hbzy0215/article/details/3998287>

 

一些奇怪错误和异常的总结:

这个是我花时间最长的东西,因为国内文档太少,因此很难确认具体原因,查了很久的GOOGLEHibernate官方文档,总算一个个搞定。

异常一

Caused by: java.util.ServiceConfigurationError:org.hibernate.integrator.spi.Integrator: Providerorg.hibernate.spatial.integration.SpatialIntegrator could not be instantiated:java.lang.NoClassDefFoundError: org/hibernate/service/spi/BasicServiceInitiator

 

Caused by: java.lang.NoClassDefFoundError:org/hibernate/service/spi/BasicServiceInitiator

 

这个错误是hibernate自身的一个BUG,4.3版本中这个类的位置不在spi中,并且名称也进行了改变。

参考官方文档

https://hibernate.atlassian.net/browse/HSEARCH-1386

 

所以后来,辛苦的试验了好几个版本,最终发现4.2.13.Final可以用

<dependency>

    <groupId>org.hibernate</groupId>

    <artifactId>hibernate-core</artifactId>

    <version>4.2.13.Final</version>

</dependency>

 

异常二

java.lang.UnsupportedOperationException

atorg.hibernate.spatial.GeometrySqlTypeDescriptor.getExtractor(GeometrySqlTypeDescriptor.java:57)

 

请确保你在cfg文件中加入了如下配置信息,并且确保hibernate-spatial的JAR包含在你的工程中。

<propertyname=“hibernate.dialect”>org.hibernate.spatial.dialect.postgis.PostgisDialect</property>

 

若是Spring配置,则需要加入

<propkey=”hibernate.dialect”>org.hibernate.spatial.dialect.postgis.PostgisDialect</prop>

 

 

至此,关于Maven 整合hibernate 和postGIS全部结束。至于整合Spring进入项目。其实只是把配置移动到Spring中。在写Spring环境下的测试类。这里暂时就不写了。以后单独写Spring的配置。

第一次写技术文档,发现是一个不错的自己总结和回忆的方式,同时也是一个很累的活。明白写文档的人的不易了。也参考了很多朋友的文档,然后一个个排查问题,查资料。最终才有我这个版本的成型。由于postGIS的资料太少,希望有研究的朋友,多多分享心得。谢谢在这条路上探索的人们。

本文档欢迎转载分享,但请注明出处。

 

把酒阁楼倚春风

2014/06/13

 

转载自:https://blog.csdn.net/thflove99/article/details/30568447

You may also like...