Uvod u Hibernate Spatial

1. Uvod

U ovom ćemo članku pogledati prostorno proširenje hibernacije, hibernacija-prostorno.

Počevši od verzije 5, Hibernate Spatial pruža standardno sučelje za rad s geografskim podacima.

2. Pozadina hibernacije u prostoru

Geografski podaci uključuju prikaz entiteta poput Točka, crta, mnogougao. Takve vrste podataka nisu dio JDBC specifikacije, stoga je JTS (JTS Topology Suite) postao standard za predstavljanje tipova prostornih podataka.

Osim JTS-a, Hibernate spatial također podržava Geolatte-geom - nedavnu knjižnicu koja ima neke značajke koje nisu dostupne u JTS-u.

Obje su knjižnice već uključene u hibernacijsko-prostorni projekt. Korištenje jedne knjižnice u odnosu na drugu jednostavno je pitanje iz kojeg jarca uvozimo tipove podataka.

Iako Hibernate prostor podržava različite baze podataka poput Oracle, MySQL, PostgreSQLql / PostGIS i nekoliko drugih, podrška za funkcije specifične za bazu podataka nije ujednačena.

Bolje je pogledati najnoviju dokumentaciju o hibernaciji kako biste provjerili popis funkcija za koje hibernacija pruža podršku za datu bazu podataka.

U ovom ćemo članku koristiti Mariadb4j u memoriji - koji održava punu funkcionalnost MySQL-a.

Konfiguracija za Mariadb4j i MySql je slična, čak i knjižnica mysql-konektora radi za obje ove baze podataka.

3. Ovisnosti Mavena

Pogledajmo Mavenove ovisnosti potrebne za postavljanje jednostavnog hibernate-prostornog projekta:

 org.hibernate hibernate-core 5.2.12.Final org.hibernate hibernate-spatial 5.2.12.Final mysql mysql-connector-java 6.0.6 ch.vorburger.mariaDB4j mariaDB4j 2.2.3 

The hibernacijski-prostorni ovisnost je ona koja će pružiti podršku za tipove prostornih podataka. Najnovije verzije hibernate-core, hibernate-spatial, mysql-connector-java i mariaDB4j mogu se dobiti od Maven Central.

4. Konfiguriranje hibernacije prostorno

Prvi korak je stvaranje a hibernirati.svojstva u resursi imenik:

hibernate.dialect = org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect // ...

Jedino što je specifično za hibernacijski prostor je MySQL56SpatialDialect dijalekt. Ovaj dijalekt proširuje MySQL55Dialect dijalekta i pruža dodatnu funkcionalnost povezanu s tipovima prostornih podataka.

Kôd specifičan za učitavanje datoteke svojstva, stvaranje a SjednicaTvornicai instanciranje instance Mariadb4j isto je kao u standardnom hibernacijskom projektu.

5. Razumijevanje Geometrija Tip

Geometrija je osnovni tip za sve prostorne tipove u ZTS-u. To znači da druge vrste poput Točka, Poligon, a drugi se protežu od Geometrija. The Geometrija vrsta u javi odgovara GEOMETRIJA upišite i MySql.

Raščlanjivanjem a Niz predstavljanje tipa, dobivamo primjerak Geometrija. Klasa korisnosti WKTReader koju pruža JTS može se koristiti za pretvaranje bilo kojeg dobro poznatog predstavljanja teksta u Geometrija tip:

public Geometry wktToGeometry (String wellK knownText) baca ParseException {return new WKTReader (). read (wellKnownText); }

Pogledajmo sada ovu metodu na djelu:

@Test javna praznina shouldConvertWktToGeometry () {Geometrija geometrija = wktToGeometry ("TOČKA (2 5)"); assertEquals ("Točka", geometry.getGeometryType ()); assertTrue (primjer geometrije točke); }

Kao što vidimo, čak i ako je vrsta povrata metode čitati() metoda je Geometrija, stvarna je instanca a Točka.

6. Pohranjivanje boda u DB-u

Sad kad imamo dobru ideju o tome što a Geometrija vrsta je i kako dobiti a Točka od a Niz, hajde da pogledamo PointEntity:

@Entity javna klasa PointEntity {@Id @GeneratedValue private Long id; privatni Point point; // standardni geteri i postavljači}

Imajte na umu da je entitet PointEntity sadrži prostorni tip Točka. Kao što je ranije pokazano, a Točka predstavljen je s dvije koordinate:

javna praznina insertPoint (točka niza) {PointEntity entitet = novi PointEntity (); entity.setPoint ((Točka) wktToGeometry (točka)); session.persist (entitet); }

Metoda insertPoint () prihvaća prikaz dobro poznatog teksta (WKT) a Točka, pretvara ga u Točka instance i sprema u DB.

Podsjećanja radi, sjednica nije specifično za hibernate-spatial i kreira se na način sličan drugom projektu hibernacije.

Ovdje možemo primijetiti da kada jednom imamo primjerak Točka stvoren, postupak spremanja PointEntity je sličan bilo kojem redovnom entitetu.

Pogledajmo neke testove:

@Test javna praznina shouldInsertAndSelectPoints () {PointEntity entitet = novi PointEntity (); entity.setPoint ((Point) wktToGeometry ("TOČKA (1 1)")); session.persist (entitet); PointEntity izDb = session .find (PointEntity.class, entity.getId ()); assertEquals ("POINT (1 1)", fromDb.getPoint (). toString ()); assertTrue (primjer geometrije točke); }

Pozivanje toString () na a Točka vraća WKT prikaz a Točka. To je zato što Geometrija klasa nadjačava toString () metoda i interno koristi WKTWriter, besplatan tečaj za WKTReader što smo vidjeli ranije.

Jednom kada pokrenemo ovaj test, hibernate će stvoriti PointEntity stol za nas.

Pogledajmo tu tablicu:

desc PointEntity; Tip polja Null key id bigint (20) NEMA PRI geometrije točke DA

Očekivano, Tip od PoljeTočka je GEOMETRIJA. Zbog toga, dok dohvaćamo podatke pomoću našeg SQL uređivača (poput MySql radnog stola), moramo pretvoriti ovaj tip GEOMETRY u tekst čitljiv čovjeku:

odaberite id, astext (point) iz PointEntity; id astext (točka) 1 TOČKA (2 4)

Međutim, kako hibernacija već vraća WKT predstavljanje kad nazovemo toString () metoda na Geometrija ili bilo koju od njegovih podrazreda, ne trebamo se truditi oko ove pretvorbe.

7. Korištenje prostornih funkcija

7.1. ST_WITHIN () Primjer

Sada ćemo pogledati upotrebu funkcija baze podataka koje rade s tipovima prostornih podataka.

Jedna od takvih funkcija u MySQL-u je ST_WITHIN () to govori hoće li jedan Geometrija je unutar drugog. Dobar primjer ovdje bio bi otkrivanje svih točaka unutar određenog radijusa.

Počnimo s gledanjem kako stvoriti krug:

javna Geometry createCircle (double x, double y, double radius) {GeometricShapeFactory shapeFactory = new GeometricShapeFactory (); shapeFactory.setNumPoints (32); shapeFactory.setCentre (nova koordinata (x, y)); shapeFactory.setSize (radijus * 2); vrati oblikFactory.createCircle (); }

Kružnica je predstavljena konačnim skupom točaka navedenih u setNumPoints () metoda. The radius udvostručuje se prije poziva setSize () metodu jer trebamo nacrtati krug oko središta, u oba smjera.

Krenimo sada naprijed i vidjet ćemo kako dohvatiti točke unutar određenog radijusa:

@Test public void shouldSelectAllPointsWithinRadius () baca ParseException {insertPoint ("POINT (1 1)"); insertPoint ("TOČKA (1 2)"); insertPoint ("TOČKA (3 4)"); insertPoint ("TOČKA (5 6)"); Upit upita = session.createQuery ("odaberite p iz PointEntity p gdje je unutar (p.point,: krug) = true", PointEntity.class); query.setParameter ("krug", createCircle (0.0, 0.0, 5)); assertThat (query.getResultList (). stream () .map (p -> ((PointEntity) p) .getPoint (). toString ())) .containsOnly ("POINT (1 1)", "POINT (1 2)) "); }

Hibernate mapira svoje unutar() funkcija na ST_WITHIN () funkcija MySql.

Ovdje je zanimljivo zapažanje da Tačka (3, 4) pada točno na kružnicu. Ipak, upit ne vraća ovu točku. Ovo je zbog the unutar() funkcija vraća true samo ako je zadana Geometrija je potpuno unutar drugog Geometrija.

7.2. ST_TOUCHES () Primjer

Ovdje ćemo predstaviti primjer koji ubacuje skup Poligons u bazi podataka i odaberite Poligons koje su susjedne danoj Poligon. Kratko ćemo pogledati PoligonEntitet razred:

@Entity javna klasa PolygonEntity {@Id @GeneratedValue private Long id; privatni poligon Poligon; // standardni geteri i postavljači}

Jedino što se ovdje razlikuje od prethodnog PointEntity jest da koristimo tip Poligon umjesto Točka.

Krenimo sada prema testu:

@Test public void shouldSelectAdjacentPolygons () baca ParseException {insertPolygon ("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))"); insertPolygon ("POLIGON ((3 0, 3 5, 8 5, 8 0, 3 0))"); insertPolygon ("POLIGON ((2 2, 3 1, 2 5, 4 3, 3 3, 2 2))"); Upit upita = session.createQuery ("odaberite p iz PolygonEntity p gdje se dodiruje (p.polygon,: polygon) = true", PolygonEntity.class); query.setParameter ("poligon", wktToGeometry ("POLIGON ((5 5, 5 10, 10 10, 10 5, 5 5))")); assertThat (query.getResultList (). stream () .map (p -> ((PolygonEntity) p) .getPolygon (). toString ())). containsOnly ("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0)) "," POLIGON ((3 0, 3 5, 8 5, 8 0, 3 0)) "); }

The insertPolygon () metoda slična je insertPoint () metoda koju smo vidjeli ranije. Izvor sadrži potpunu provedbu ove metode.

Koristimo dodiri () funkcija za pronalaženje Poligons uz određeni Poligon. Jasno, treći Poligon se ne vraća u rezultat jer nema ruba koji dodiruje dano Poligon.

8. Zaključak

U ovom smo članku vidjeli da hibernate-spatial čini postupanje s tipovima prostornih podataka puno jednostavnijim jer se brine o detaljima niske razine.

Iako ovaj članak koristi Mariadb4j, možemo ga zamijeniti MySqlom bez mijenjanja bilo kakve konfiguracije.

Kao i uvijek, puni izvorni kod za ovaj članak nalazi se na GitHubu.


$config[zx-auto] not found$config[zx-overlay] not found