PostGIS dan JPA



PostGIS adalah perangkat lunak sumber terbuka yang menambahkan dukungan untuk fitur geografis ke database relasional PostgreSQL.

Artikel singkat ini akan membahas penggunaannya di Jawa. Secara khusus, tugas menemukan objek geografis berdasarkan koordinatnya.

PostGIS dibuat kembali pada tahun 2001. Ini adalah solusi gratis yang baik untuk menyimpan data peta dalam database. Tetapi artikel ini tidak sepenuhnya tentang dia, tetapi hanya tentang kasus khusus - kerja yang mudah dengan PostGIS menggunakan alat JPA.

Ketergantungan


Perpustakaan berikut ini penting untuk tugas kami:

  • Hibernasi 5.3.7
  • hibernate-spatial - versi yang sama. Secara teoritis, Anda dapat menggunakan yang lebih lama. Mulai di urutan kelima, hibernate-spatial sama dengan hibernate. Sebelumnya: Hibernate Spatial 1.1.x untuk Hibernate 3.6.x, Hibernate Spatial 1.0 untuk Hibernate 3.2.x - 3.5.x.
  • postgresql 42.2.4. Versi ini diambil, karena yang lebih baru memperketat persyaratan SSL. Pilih versi driver yang cocok dengan versi database.

Nah, yang Anda butuhkan untuk JPA adalah Spring atau wadah.

Dialek


Hibernate Spatial menyediakan abstraksi geometris untuk bekerja dengan basis spasial. Seperti pada JPA, sebagai perkiraan pertama, kami tidak tertarik pada basis data mana yang digunakan pada server.

Secara resmi didukung oleh PostgresSQL, Oracle, MySQL, MS SQLServer, GeoDB (H2), DB2. Fitur detail dukungan . Otot mungkin tampak seperti orang luar. Tetapi dalam versi 8, dukungan data spasial ditingkatkan dengan layak.

Kami menggunakan Postgres. Tetapi Anda perlu menentukan dialek Hibernate "org.hibernate.spatial.dialect.postgis.PostgisDialect" alih-alih yang standar pasca-Yunani.

Sudah waktunya untuk kode


Tabel di PostGIS dapat memiliki bidang apa saja. Cukup standar, salah satunya akan berjenis geometri. Dan ada geografi (tidak didukung sekarang di Hibernate). Jika Anda tidak mengajarkan Java untuk bekerja dengan tipe ini, itu akan ditafsirkan sebagai gumpalan atau String dari bentuk "01010000207B7F0000188D594CC9B22541BC4E56674F2C5541".

Tentu saja, Anda dapat bekerja dengan PostGis pada JBDC murni. Sebuah contoh Tetapi ini membutuhkan kerja keras yang terpisah dengan org.postgis.PGgeometry . Ini bukan kelas yang akan menjadi artikelnya. Dan tidak akan ada toleransi lagi.

Kami pergi ke JPA dan membuat kelas sederhana:

 @Entity public class AdressBuilding implements Serializable { @Id private Integer id; private Point geom; ... 

Kolom yang tersisa dihilangkan (objek geografis dapat menyimpan informasi apa pun). Tidak ada yang aneh di sini - kelas entitas standar. Hanya objek kelas Point yang menarik - titik ruang tiga dimensi.

Selanjutnya, kelas dari paket com.vividsolutions.jts.geom digunakan.

JTS telah menjadi standar de facto untuk mewakili data geospasial. Ini mengimplementasikan Spesifikasi Fitur Sederhana / Spesifikasi Akses Fitur Sederhana yang dibuat oleh OpenGIS di tahun 90an.

Klarifikasi . Point mewarisi dari kelas Geometri abstrak. Ini berisi bidang non-statis berikut:

  protected Envelope envelope; protected final GeometryFactory factory; protected int SRID; private Object userData; 

Amplop adalah kotak pembatas minimum untuk geometri ini. Tapi itu bisa kembali dalam bentuk geometri. Dan kemudian Anda akan memiliki upaya serialisasi yang tak berkesudahan.

SRID - mengoordinasikan nomor sistem. Ada banyak dari mereka. Perbedaan utama: format koordinat (meter, derajat ...), titik referensi dan bentuk Bumi (Bumi tidak bulat). PostGis tahu banyak sistem koordinat dan dapat mengubahnya.

Seperti yang saya katakan, kami memiliki tipe geometri dalam database. Saya langsung menggunakan kelas Titik konkret untuk kenyamanan, karena dalam tabel ini saya hanya memiliki objek titik. Tetapi teori PostGIS dapat menyimpan beberapa jenis geometri sekaligus. Hanya di setiap geometri jenisnya ditunjukkan:

 "geometry":{"type":"MultiPolygon","coordinates":... 

Menurut StackOverflow, menggunakan beberapa geometri di tabel yang sama memperlambat permintaan. Geometri juga bisa disarangkan. Jenis:


Permintaan Basis Data


Dengan implementasi kelas tahu. sekarang saatnya untuk mendapatkannya dari pangkalan. Poin kami adalah rumah, atau lebih tepatnya alamat mereka. Anda dapat membuat kueri SQL yang familier: dapatkan rumah dengan id, jumlah, jumlah nenek ...

Kami sekarang tertarik dengan pertanyaan spasial. Misalnya, cari rumah dengan koordinat. Biarkan koordinat yang diinginkan x, y, dan + -delta menjadi area pencarian yang diinginkan. Pertanyaan utama dalam STS dilakukan pada rasio geometri. Karena itu, kita perlu membuatnya:

  Coordinate c1 = new Coordinate(x - delta, y - delta); ... Coordinate[] coordinates = new Coordinate[]{c1, c2, c3, c4, c1}; GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();//static  Polygon square_window = GEOMETRY_FACTORY.createPolygon(coordinates); square_window.setSRID(32635); 

Jika kami tidak menentukan sistem koordinat, PostGis akan menolak untuk membandingkannya. Anda juga tahu kode sistem Anda, atau dapatkan dari mana saja dengan kode .getGeom().getSRID() .

Selanjutnya kami mengirim permintaan formulir:

  "select a " + "from AdressBuilding a " + "where within(a.geom, :window) = true" 

Kueri di dalam berarti memeriksa apakah geometri di dalam yang lain. Jangan khawatir jika IDE Anda mengatakan bahwa tidak ada permintaan seperti itu di JPA. Hibernate Spatial mengubahnya menjadi:
  where st_within(adressbuil0_.geom, ?)=true 

Di mana st_within sudah menjadi fungsi PostGis.

Ada beberapa opsi untuk bagaimana mendapatkan hasil yang sama - intinya jatuh ke bujur sangkar. contains(:window, a.geom) / intersects(a.geom, :window)...



Penjelasan terperinci dari spesifikasi ada di sini .

Kata penutup


Kami mendapat poin - sekarang lakukan apa pun yang Anda inginkan dengan mereka.

Saya menguji kasus database kecil di server dengan jumlah RAM yang relatif besar. Jika Anda memuat secara maksimal dan melupakan indeks, tugas pencarian akan berjalan ke prosesor.
Postgres memiliki banyak indeks berbeda. Dan beberapa dari mereka membantu Postgis . Studi menunjukkan bahwa hanya GIST (?) Yang cocok untuk poin
 CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] ); 

Tetapi paling sering, ketika Anda mengimpor data ke PostGis, indeks dibuat secara otomatis ...

Klarifikasi dan informasi tambahan dipersilahkan.

Manual yang digunakan:

Untuk hibernasi 5
Untuk hibernasi 4

Source: https://habr.com/ru/post/id440872/


All Articles