Jason ---分享,共同進步

          激情成就夢想,努力創(chuàng)造未來
          隨筆 - 53, 文章 - 1, 評論 - 45, 引用 - 0
          數(shù)據(jù)加載中……

          hibernate 支持 postgis函數(shù)


          今天上午一位朋友問到了,關(guān)于hibernate中是否支持postgis函數(shù)的問題,我就這個問題,隨便聊幾句。


          要想使用hibernate的空間數(shù)據(jù)操作,就要提到一個概念 java Topology Suite (字面上理解就是 空間拓撲的意思,簡稱JTS,
          注意:過需要聲明一點,本文中的JTS與進行java事務(wù)處理的JTS、JTA沒有聯(lián)系).

          HIBERNATE中對空間數(shù)據(jù)作了支持(Hibernate Spatial),Hibernate Spatial是對處理空間數(shù)據(jù)的一個Hibernate擴展 ,

          Hibernate Spatial 使用標準的方式處理地理信息數(shù)據(jù) ,并且提供了一個可以跨數(shù)據(jù)庫的處理的接口函數(shù),

          Hibernate Spatial 中包含了多種 OGC 簡單的處理函數(shù). 支持的數(shù)據(jù)庫為: Oracle 10g/11g, Postgresql/Postgis, and MySQL.

          要想使用 Hibernate Spatial  就要引入JTS, JTS 從根本上而言其實并不是很復(fù)雜,它主要是完成了java對幾何對象、空間拓撲得核心操作算法。

          下面通過簡單配置來說明一下如何使用(我們使用的數(shù)據(jù)庫是postgis):

          數(shù)據(jù)庫腳本:
          sql:

          CREATE TABLE events
          (
            id bigint NOT NULL,
            event_date timestamp without time zone,
            title character varying(255),
            "location" geometry,
            CONSTRAINT events_pkey PRIMARY KEY (id)
          )


          1,引入 jts-1.8.jar, hibernate3.jar 等包 ,同時還要應(yīng)用 hibernate-spatial-postgis-1.0-20070920.111959-1.jar 和
          hibernate-spatial-1.0-20070920.111959-1.jar 包(如果不是postgre sql就要引用相應(yīng)的數(shù)據(jù)庫包)。


          2,創(chuàng)建一個持久化類(po對象)

          如下:
          import java.util.Date;
          import com.vividsolutions.jts.geom.Point;

          public class Event {
              
          private Long id;
              
          private String title;
              
          private Date date;
              
          private Point location;

              
          public Event() {}

              
          public Long getId() {
                  
          return id;
              }


              
          private void setId(Long id) {
                  
          this.id = id;
              }


              
          public Date getDate() {
                  
          return date;
              }


              
          public void setDate(Date date) {
                  
          this.date = date;
              }


              
          public String getTitle() {
                  
          return title;
              }


              
          public void setTitle(String title) {
                  
          this.title = title;
              }

              
              
          public Point getLocation(){
              
          return this.location;
              }

              
              
          public void setLocation(Point location){
              
          this.location = location;
              }

          }
          注意:上面的po對象中的location屬性的類型。這個類型是空間數(shù)據(jù)類型。

          3,創(chuàng)建相應(yīng)的Mapping 文件

          <hibernate-mapping>
          <class name="Event" table="EVENTS">
          <id name="id" column="EVENT_ID">
          <generator class="native"/>
          </id>
          <property name="date" type="timestamp" 
          column
          ="EVENT_DATE"/>
          <property name="title"/>
          <property name="location" 
          type
          ="org.hibernatespatial.GeometryUserType" 
          column
          ="location"/>
          </class>
          </hibernate-mapping>
          注意:在上面的影射文件中,type="org.hibernatespatial.GeometryUserType" 這type類型聲明很特別,我們知道在hibernate中要自定義影射類型,可以自定義類型UserType.在這個配置文件中定義的類型org.hibernatespatial.GeometryUserType就是hibernatespatial中定義支持空間數(shù)據(jù)庫的類型。

          4,配置hibernate 配置文件
          <?xml version='1.0' encoding='utf-8'?>
          <!DOCTYPE hibernate-configuration PUBLIC
                  "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"
          >

          <hibernate-configuration>

              
          <session-factory>

                  
          <!-- Database connection settings -->
                  
          <property name="connection.driver_class">org.postgresql.Driver</property>
                  
          <property name="connection.url">jdbc:postgresql://localhost:5432/test</property>
                  
          <property name="connection.username">postgres</property>
                  
          <property name="connection.password">test</property>

                  
          <!-- JDBC connection pool (use the built-in) -->
                  
          <property name="connection.pool_size">1</property>

                  
          <!-- SPATIAL SQL dialect -->
                  
          <property name="dialect">org.hibernatespatial.postgis.PostgisDialect</property>

                  
          <!-- Enable Hibernate's automatic session context management -->
                  
          <property name="current_session_context_class">thread</property>

                  
          <!-- Disable the second-level cache  -->
                  
          <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

                  
          <!-- Echo all executed SQL to stdout -->
                  
          <property name="show_sql">true</property>

                  
          <!-- Drop and re-create the database schema on startup -->
                  
          <property name="hbm2ddl.auto">create</property>

                  
          <mapping resource="Event.hbm.xml"/>

              
          </session-factory>

          </hibernate-configuration>
          注意:在上面的配置文件中, <property name="dialect">org.hibernatespatial.postgis.PostgisDialect</property>
          這句配置起到了重要的作用,這里聲明了 hibernate 的方言。該方言聲明了對postgis的一些支持。
          并且大家也應(yīng)該知道,在使用hibernate時候,如果需要自定義函數(shù),要需要自定義方言。


          5,第一個主類


          import org.hibernate.Criteria;
          import org.hibernate.Query;
          import org.hibernate.Session;
          import org.hibernatespatial.criterion.SpatialRestrictions;
          import org.postgis.Geometry;
          import org.postgis.LineString;
          import org.postgis.MultiLineString;
          import org.postgis.MultiPolygon;
          import org.postgis.PGgeometry;
          import org.postgis.Polygon;

          import com.vividsolutions.jts.geom.Point;
          import com.vividsolutions.jts.io.ParseException;
          import com.vividsolutions.jts.io.WKTReader;
          import com.vividsolutions.jts.geom.*;
          import java.util.Date;
          import java.util.List;

          import util.HibernateUtil;

          public class EventManager {

              
          public int SRID = 4326;

              
          public static void main(String[] args) {
                  EventManager mgr 
          = new EventManager();

                  String testPiont 
          = "2,3";
                  mgr.createAndStoreEvent(
          "My Event"new Date(), testPiont);
              

                  HibernateUtil.getSessionFactory().close();
              }


              
          private void createAndStoreEvent(String title, Date theDate, String wktPoint) {
                  
                  com.vividsolutions.jts.geom.Geometry geom 
          = null;
                  
          try {
                      geom 
          = pointFromText(wktPoint);
                  }
           catch (Exception e) {
                      
          throw new RuntimeException("Not a WKT string:" + wktPoint);
                  }


                  Session session 
          = HibernateUtil.getSessionFactory().getCurrentSession();

                  session.beginTransaction();

                  Event theEvent 
          = new Event();
                  theEvent.setTitle(title);
                  theEvent.setDate(theDate);
                  theEvent.setLocation((Point) geom);
                  session.save(theEvent);
                  session.flush();
                  session.getTransaction().commit();
                  List l
          = find("POLYGON((1 1,20 1,20 20, 1 20, 1 1))");
                  
                  System.out.println(l.size());
                  
                  List l1
          = find1("POLYGON((1 1,20 1,20 20, 1 20, 1 1))");
                  
                  System.out.println(l1.size());
              }

              
              
          private List find(String wktFilter){
                  WKTReader fromText 
          = new WKTReader();
                  com.vividsolutions.jts.geom.Geometry filter 
          = null;
                  
          try{
                          filter 
          = fromText.read(wktFilter);
                          filter.setSRID(SRID);
                  }
           catch(ParseException e){
                          
          throw new RuntimeException("Not a WKT String:" + wktFilter);
                  }

                  Session session 
          = HibernateUtil.getSessionFactory().getCurrentSession();
                  session.beginTransaction();
                  System.out.println(
          "Filter is : " + filter);
                  Criteria testCriteria 
          = session.createCriteria(Event.class);
                  testCriteria.add(SpatialRestrictions.within(
          "location", filter, filter));
                  List results 
          = testCriteria.list();
                  session.getTransaction().commit();
                  
          return results;
              }

              
              
          private List find1(String wktFilter){
                  WKTReader fromText 
          = new WKTReader();
                  com.vividsolutions.jts.geom.Geometry filter 
          = null;
                  
          try{
                          filter 
          = fromText.read(wktFilter);
                          filter.setSRID(SRID);
                  }
           catch(ParseException e){
                          
          throw new RuntimeException("Not a WKT String:" + wktFilter);
                  }

                  Session session 
          = HibernateUtil.getSessionFactory().getCurrentSession();
                  session.beginTransaction();
                  
                  Query query 
          = session.createQuery("select within(location,'srid=4326;POLYGON ((1 1, 20 1, 20 20, 1 20, 1 1))') from Event ");

                  List list 
          = query.list();
                  
          return list;
              }



              
          public Point pointFromText(String txt) throws Exception {

                  String tmp 
          = txt;
                  
          if (!tmp.startsWith("POINT")) {
                      tmp 
          = tmp.replace(","" ");
                      tmp 
          = "POINT(" + tmp + ")";
                  }


                  
          try {
                        WKTReader fromText 
          = new WKTReader();
                          Geometry  geom 
          = fromText.read(tmp);
                          
                      
                      Point pt 
          = (Point) fromText.read(tmp);
                      pt.setSRID(SRID);
                      
          return pt;
                  }
           catch (Exception e) {
                      
          return null;
                  }

              }



              }

          通過上面的方法,我們可以測試出來,hibernate已經(jīng)可以支持空間數(shù)據(jù)類型的數(shù)據(jù)操作了,可以實現(xiàn)空間數(shù)據(jù)入庫到空間數(shù)據(jù)對象影射到j(luò)ava對象中(插入和查詢方法),但是有一個問題,就是支持的空間數(shù)據(jù)操作方法太少了。例如 contains,disjoint,within等十幾個方法。這些方法都是簡單的空間數(shù)據(jù)操作方法,要想實現(xiàn)復(fù)雜的空間數(shù)據(jù)這還遠遠不夠的。相對于這方面來說ibatis 就很方便的使用了。

          這方面的資料比較少,大家都交流 ,有什么好的經(jīng)驗大家分享一下。 

           

          posted on 2008-07-15 23:05 agun 閱讀(2799) 評論(7)  編輯  收藏 所屬分類: 架構(gòu)設(shè)計與系統(tǒng)分析

          評論

          # re: hibernate 支持 postgis函數(shù)  回復(fù)  更多評論   

          我用HQL去查詢結(jié)果(hibernate+postgis)
          select t.fname from Tgpoi t where t.ftcd=111;

          select asText(t.the_geom) from Tgpoi t where t.ftcd=111;

          都可以查找出來

          但我想得到多個字段的話,輸出:
          Ljava.lang.Object;@232dsfdff

          請問一下如何能得到某條記錄所有的值
          2008-07-16 13:20 | ads

          # re: hibernate 支持 postgis函數(shù)  回復(fù)  更多評論   

          又來麻煩你了,
          hibernate 與 postgis 結(jié)合可以看看這個
          http://www.hibernatespatial.org/tutorial.html
          上面說的還不錯,提供大家參考
          2008-07-16 13:38 | ads

          # re: hibernate 支持 postgis函數(shù)  回復(fù)  更多評論   

          呵呵,這個文章很好,你上面說想得到多個字段,hibernate查詢輸出的一定是對象。
          如果是 select asText(t.the_geom) ,asText(t.the_geom) from Tgpoi t where t.ftcd=111;
          這樣的HQL,那么
          Query query = session.createQuery("select asText(t.the_geom) ,asText(t.the_geom) from Tgpoi t where t.ftcd=111");
          List l= query.list();
          System.out.println(((List)l.get(0)).get(0).toString());
          System.out.println(((List)l.get(0)).get(1).toString());
          這樣就能分別拿到查詢了列了。
          不知道你不是你說的意思。多交流。
          2008-07-17 13:57 | agun

          # re: hibernate 支持 postgis函數(shù)  回復(fù)  更多評論   

          呵呵
          謝謝了
          我做出來了,主要問題出在了
          我的驅(qū)動包引錯了,大大的失誤
          嘿嘿!!現(xiàn)在學習這個,資料太小,幾乎都是外文的,可憐我的外文水平!!!
          2008-07-28 10:54 | ads

          # re: hibernate 支持 postgis函數(shù)  回復(fù)  更多評論   

          呵呵,出來就好,現(xiàn)在這方面的中文的資料不是很多,hibernate的postgis支持不是很好,許多gis函數(shù)都需要自己聲明。有什么好的資料,到時候都拿出來分享,一起學習。
          2008-07-29 16:31 | agun

          # re: hibernate 支持 postgis函數(shù)  回復(fù)  更多評論   

          如果是大量的GIS開發(fā),最好不要用HIBERNATE即使用上面地方法能夠支持,也只是支持不多的幾個函數(shù),要想做更多更好的空間處理,用ibatis可以很容易結(jié)合自己的Handler Type來處理。
          2010-11-29 11:17 | agun

          # re: hibernate 支持 postgis函數(shù)  回復(fù)  更多評論   

          這個項目文件還有沒有?可不可以拷我一份?最近需要用到這個但是一直搞不定!!我的郵箱是:youdianshen@126.com
          2013-03-20 11:31 | 沈維海

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          主站蜘蛛池模板: 平凉市| 承德县| 新晃| 安乡县| 嘉兴市| 石首市| 历史| 大厂| 吴堡县| 宁陕县| 宝丰县| 来宾市| 本溪市| 墨玉县| 宜昌市| 买车| 武平县| 西吉县| 本溪市| 苍溪县| 澎湖县| 寻乌县| 冀州市| 通城县| 元氏县| 沈阳市| 和林格尔县| 山阴县| 宝坻区| 公主岭市| 仪征市| 芦山县| 张家界市| 双流县| 安远县| 梅河口市| 阜康市| 马关县| 菏泽市| 沧州市| 小金县|