Java讀取數據庫Geometry

簡介

最近因爲需要存一些經緯度塊信息到數據庫,所以用到了mysql中的Geometry屬性(幾何對象)。在網上搜集了很多資料,到真正用的時候還是各種問題,所以下面推薦一種可能有點笨但是實用的方法(我的使用環境springboot工具是sts),下面就舉個例子來說明一下。

操作

先了解一下數據庫中空間數據類型有哪些
 

類型 說明 簡介 例子
Geometry 間數據 任意一種空間類型  
Point 座標值 POINT(104.00924 30.46872)
LineString 線,由一系列點連接而成 LINESTRING(1 1,  1 1, 1 1)
Polygon 多邊形 由多條線組成 POLYGON((1 1, 2 2, 3 3,  4 4, 5 5))
MultiPoint 點集合 集合類,包含多個點 MULTIPOINT(1 1, 2 2, 1 1)
MultiLineString 線集合 集合類,包含多條線 MULTILINESTRING((1 1, 2 2), (1 1, 1 1))
MultiPolygon 多邊形集合 集合類,包含多個多邊形 MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0)), ((1 1, 1 1, 1 1, 1 1, 1 1)))
GeometryCollection 空間數據集合 集合類,可以包括多個點、線、多邊形 GEOMETRYCOLLECTION(POINT(1 1), POINT(3 3), LINESTRING(1 1, 2 2))

 

接着往數據庫插入一個測試數據,插入的是一個空間數據集合裏面包含多個多邊形集合。

 

INSERT INTO `geometry`(`geome`) VALUES(GeomFromText('GEOMETRYCOLLECTION(MULTIPOLYGON(((104.009241 30.468972,104.009229 30.468961,104.009225 30.468997)),((104.009241 30.468972,104.009229 30.468961,104.009225 30.468997))),MULTIPOLYGON(((104.009241 30.468972,104.009229 30.468961,104.009225 30.468997))))'));

數據準備好了就準備開始準備讀取操作。

在pom.xml添加操作Geometry等對象的依賴。

<dependency>
    <groupId>com.vividsolutions</groupId>
    <artifactId>jts</artifactId>
    <version>1.13</version>
</dependency>

本來先是想直接在實體類確定類型直接轉對象,但是用了後發現不行,所以我就直接設置成Object,在mysql中存儲Geometry使用的是二進制,所以下面直接把二進制通過jts轉成Geometry對象。

//private Geometry geom; 不可行
private Object geomAsBytes; //可行  最終得到的是一個byte數組
	 //直接把數據庫中的byte[]轉Geometry對象
  public static Geometry getGeometryByBytes( byte[]  geometryAsBytes) throws Exception {
           Geometry dbGeometry = null;
               // 字節數組小於5,說明geometry有問題
               if (geometryAsBytes.length < 5) {
                                     return null;
               }

               //這裏是取字節數組的前4個來解析srid
               byte[] sridBytes = new byte[4];
               System.arraycopy(geometryAsBytes, 0, sridBytes, 0, 4);
               boolean bigEndian = (geometryAsBytes[4] == 0x00);
               // 解析srid
               int srid = 0;
               if (bigEndian) {
                   for (int i = 0; i < sridBytes.length; i++) {
                       srid = (srid << 8) + (sridBytes[i] & 0xff);
                   }
               } else {
                   for (int i = 0; i < sridBytes.length; i++) {
                       srid += (sridBytes[i] & 0xff) << (8 * i);
                   }
               }
               //use the JTS WKBReader for WKB parsing
               WKBReader wkbReader = new WKBReader();
               // 使用geotool的WKBReader 把字節數組轉成geometry對象。
               byte[] wkb = new byte[geometryAsBytes.length - 4];
               System.arraycopy(geometryAsBytes, 4, wkb, 0, wkb.length);
               dbGeometry = wkbReader.read(wkb);
               dbGeometry.setSRID(srid);
           return dbGeometry;
       }

完整使用例子,解析數據庫中的geometry對象,得到我們需要的點位數據。

//返回一個區域集合  區域由若干個點組成
public List < Area > geometryCollection2PressAreas(byte[] data) {
	List < Area > areas= new ArrayList < > ();
 	try {
       //解析出空間集合層
		GeometryCollection geometryCollection = (GeometryCollection) GeometryUtil.getGeometryFromInputStream(data);
		int geometrySize = geometryCollection.getNumGeometries();
		for (int i1 = 0; i1 < geometrySize; i1++) {
			try {
               //解析出多邊形集合層
				MultiPolygon multiPolygon = (MultiPolygon) geometryCollection.getGeometryN(i1);
				int size = (int) multiPolygon.getNumPoints();
				for (int i = 0; i < size; i++) {
					try {
                        //解析出多邊形
						Polygon polygon = (Polygon) multiPolygon.getGeometryN(i);
                        //解析出多邊形中的多個點位
						Coordinate[] coordinates2 = polygon.getCoordinates();
						int size2 = coordinates2.length;
						Area area = new Area();
						area.area_pts = new ArrayList < > ();
						for (int j = 0; j < size2; j++) {
                            //點位對象 就一個x,一個y數據
							Point point = new Point();
							point.x = coordinates2[j].x;
							point.y = coordinates2[j].y;
                            //點位集合
							area.area_pts.add(point);
						}
						areas.add(area);
					} catch (Exception e) {
						break;
					}
				}
			} catch (Exception e) {
				break;
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
	return areas;
}

 

總結

其實以前存地理信息都是用的自己組裝的json字符串,佔用空間太大。最近才發現mysql還有地理空間數據這個好東(發現新大陸~),空間節省了,讀取也快了。不過讀取數據庫中數據不知道還有沒有更好的方法,這篇介紹的都是自己手動轉的對象,不過暫時先能用就好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章