Bevezetés a hibernált térbe

1. Bemutatkozás

Ebben a cikkben megnézzük a hibernált, a hibernált-térbeli térbeli kiterjesztést.

Az 5. verziótól kezdve, A Hibernate Spatial szabványos felületet biztosít a földrajzi adatokkal való munkavégzéshez.

2. A hibernált tér háttere

A földrajzi adatok magukban foglalják az olyan entitások ábrázolását, mint a Pont, vonal, sokszög. Az ilyen adattípusok nem képezik a JDBC specifikáció részét, ezért a JTS (JTS Topology Suite) a téradattípusok képviseletének szabványává vált.

A Hibernate spatial a JTS mellett támogatja a Geolatte-geom-ot is - egy nemrégiben használt könyvtár, amelynek vannak olyan tulajdonságai, amelyek a JTS-ben nem érhetők el.

Mindkét könyvtár már benne van a hibernált térbeli projektben. Az egyik könyvtár használata a másikkal egyszerűen az a kérdés, hogy melyik üvegből importálunk adattípusokat.

Bár a Hibernate spatial különböző adatbázisokat támogat, mint például az Oracle, MySQL, PostgreSQLql / PostGIS és még néhány más, az adatbázis-specifikus funkciók támogatása nem egységes.

Jobb, ha a legújabb hibernált dokumentációra hivatkozik, hogy ellenőrizze azoknak a funkcióknak a listáját, amelyeknél a hibernálás támogatja az adott adatbázist.

Ebben a cikkben egy memóriában lévő Mariadb4j-t fogunk használni - amely fenntartja a MySQL teljes funkcionalitását.

A Mariadb4j és a MySql konfigurációja hasonló, még a mysql-connector könyvtár is működik mindkét adatbázisban.

3. Maven-függőségek

Vessünk egy pillantást az egyszerű hibernált-térbeli projekt felállításához szükséges Maven-függőségekre:

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

A hibernált-térbeli a függőség az, amely támogatást nyújt a téradattípusokhoz. A hibernate-core, hibernate-spatial, mysql-connector-java és a mariaDB4j legújabb verziói a Maven Central webhelyről szerezhetők be.

4. A hibernált tér konfigurálása

Az első lépés a hibernálni.tulajdonságok ban,-ben erőforrások Könyvtár:

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

Az egyetlen dolog, ami kifejezetten hibernált-térbeli, az a MySQL56SpatialDialect nyelvjárás. Ez a nyelvjárás kiterjeszti a MySQL55Dialect nyelvjárást és további funkciókat biztosít a téradattípusokkal kapcsolatban.

A tulajdonságfájl betöltésére, a SessionFactory, és a Mariadb4j példány példányosítása megegyezik egy szokásos hibernált projekttel.

5. A Geometria típus

Geometria a JTS összes tértípusának alaptípusa. Ez azt jelenti, hogy más típusok is szeretik Pont, Poligonés mások kiterjednek Geometria. A Geometria A java típus megfelel a GEOMETRIA írja be a MySql-t is.

A. Elemzésével Húr a típus ábrázolása, kapunk egy példányát Geometria. Hasznossági osztály WKTReader a JTS által biztosított bármely jól ismert szöveges ábrázolás a-vá konvertálására Geometria típus:

public Geometry wktToGeometry (String wellKnownText) dobja a ParseException {return new WKTReader (). read (wellKnownText); }

Nézzük meg ezt a módszert működés közben:

@Test public void shouldConvertWktToGeometry () {Geometry geometry = wktToGeometry ("POINT (2 5)"); assertEquals ("Pont", geometry.getGeometryType ()); assertTrue (a pont geometriai példánya); }

Mint láthatjuk, még akkor is, ha a módszer visszatérési típusa az olvas() módszer az Geometria, a tényleges példány az a Pont.

6. Pont tárolása a DB-ben

Most, hogy van egy jó ötletünk arról, mi a Geometria típus és hogyan lehet a Pont ki a Húr, vessünk egy pillantást a PointEntity:

@Entity public class PointEntity {@Id @GeneratedValue private Long id; privát Pont pont; // szabványos mérőeszközök és beállítók}

Vegye figyelembe, hogy az entitás PointEntity térbeli típust tartalmaz Pont. Amint azt korábban bemutattuk, a Pont két koordináta képviseli:

public void insertPoint (String point) {PointEntity entitás = new PointEntity (); entitás.setPoint ((Pont) wktToGeometry (pont)); session.persist (entitás); }

A módszer, a metódus insertPoint () elfogad egy jól ismert szöveges (WKT) ábrázolást a Pont, átalakítja a-vá Pont példányt, és ment a DB-be.

Emlékeztetőül: ülés nem specifikus a hibernált térben, és egy másik hibernált projekthez hasonló módon jön létre.

Itt észrevehetjük, hogy ha egyszer van egy példányunk Pont létrehozása, a tárolás folyamata PointEntity hasonló minden rendes entitáshoz.

Nézzünk meg néhány tesztet:

@Test public void shouldInsertAndSelectPoints () {PointEntity entitás = new PointEntity (); entitás.setPoint ((Pont) wktToGeometry ("PONT (1 1)")); session.persist (entitás); PointEntity fromDb = session .find (PointEntity.class, entitás.getId ()); assertEquals ("POINT (1 1)", fromDb.getPoint (). toString ()); assertTrue (a pont geometriai példánya); }

Hívás toString () rajta Pont a WKT reprezentációját adja vissza Pont. Ez azért van, mert a Geometria osztály felülírja a toString () módszerrel és belsőleg használja WKTWriter, egy ingyenes osztály WKTReader amit korábban láttunk.

Miután lefuttattuk ezt a tesztet, a hibernálás létrejön PointEntity asztal nekünk.

Vessünk egy pillantást arra a táblázatra:

desc PointEntity; Mező típusa Null Key id bigint (20) NINCS PRI pont geometria IGEN

Ahogy az várható volt, a típus nak,-nek TerületPont van GEOMETRIA. Emiatt, miközben az adatokat az SQL-szerkesztőnk segítségével (például MySql munkapad) töltjük le, át kell alakítanunk ezt a GEOMETRY típust ember által olvasható szöveggé:

válassza ki az id, astext (point) pontot a PointEntity-ből; id astext (pont) 1 PONT (2 4)

Mivel azonban a hibernálás már visszaadja a WKT reprezentációt, amikor hívunk toString () módszer be Geometria vagy bármelyik alosztálya, nem kell aggódnunk ezen átalakítás miatt.

7. Térbeli funkciók használata

7.1. ST_WITHIN () Példa

Most áttekintjük a téradattípusokkal működő adatbázis-funkciók használatát.

A MySQL egyik ilyen funkciója ST_WITHIN () ez megmondja, hogy az egyik Geometria egy másikon belül van. Jó példa erre az, ha megtudja az összes pontot egy adott sugarú körön belül.

Kezdjük azzal, hogy megvizsgáljuk, hogyan hozhatunk létre egy kört:

public Geometry createCircle (dupla x, dupla y, dupla sugár) {GeometricShapeFactory shapeFactory = új GeometricShapeFactory (); shapeFactory.setNumPoints (32); shapeFactory.setCentre (új koordináta (x, y)); shapeFactory.setSize (sugár * 2); return shapeFactory.createCircle (); }

A kört a. Által megadott véges pontkészlet képviseli setNumPoints () módszer. A sugár megduplázódik, mielőtt felhívná a setSize () módszer, mivel meg kell rajzolnunk a kört a középpont körül, mindkét irányban.

Most lépjünk előre, és nézzük meg, hogyan lehet lekérni a pontokat egy adott sugarú körön belül:

@Test public void shouldSelectAllPointsWithinRadius () dobja a ParseException {insertPoint ("POINT (1 1)"); insertPoint ("POINT (1 2)"); insertPoint ("POINT (3 4)"); insertPoint ("POINT (5 6)"); Lekérdezés = session.createQuery ("válasszon p-t a PointEntity p-ből, ahol benne van (p.point,: kör) = true", PointEntity.class); query.setParameter ("kör", createCircle (0,0, 0,0, 5)); assertThat (query.getResultList (). stream () .map (p -> ((PointEntity) p) .getPoint (). toString ())) .ConlyOnly ("POINT (1 1)", "POINT (1 2)" "); }

A hibernálás feltérképezi belül() funkció a ST_WITHIN () a MySql funkciója.

Érdekes megfigyelés, hogy a (3, 4) pont pontosan a körre esik. Ennek ellenére a lekérdezés nem adja vissza ezt a pontot. Ez azért van, mert a belül() függvény csak akkor tér vissza igazra, ha az adott Geometria teljesen egy másikban van Geometria.

7.2. ST_TOUCHES () Példa

Itt bemutatunk egy példát, amely beilleszt egy halmazt Poligons az adatbázisban, és válassza ki a Poligonamelyek szomszédosak egy adott Poligon. Vessünk egy gyors pillantást a PolygonEntity osztály:

@Entity public class PolygonEntity {@Id @GeneratedValue private Long id; saját sokszög sokszög; // szabványos mérőeszközök és beállítók}

Az egyetlen dolog itt eltér az előzőtől PointEntity az, hogy a típust használjuk Poligon a helyett Pont.

Menjünk most a teszt felé:

@Test public void shouldSelectAdjacentPolygons () dobja a ParseException {insertPolygon ("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))"); insertPolygon ("POLYGON ((3 0, 3 5, 8 5, 8 0, 3 0)"); insertPolygon ("POLYGON ((2 2, 3 1, 2 5, 4 3, 3 3, 2 2))"; Lekérdezés = session.createQuery ("válasszon p-t a PolygonEntity p-ről, ahol megérinti (p.polygon,: sokszög) = true", PolygonEntity.class); query.setParameter ("sokszög", wktToGeometry ("POLYGON ((5 5, 5 10, 10 10, 10 5, 5 5))"); assertThat (query.getResultList (). stream () .map (p -> ((PolygonEntity) p) .getPolygon (). toString ())). Csak CSAK ("POLYGON ((0 0, 0 5, 5 5, 5) 0, 0 0)) "," POLYGON ((3 0, 3 5, 8 5, 8 0, 3 0)) "); }

A insertPolygon () módszer hasonló a insertPoint () módszer, amelyet korábban láttunk. A forrás tartalmazza a módszer teljes megvalósítását.

Használjuk a érintések () függvény a Poligons szomszédos egy adott Poligon. Nyilvánvaló, hogy a harmadik Poligon nem jelenik meg az eredményben, mivel nincs él, amely az adottat érinti Poligon.

8. Következtetés

Ebben a cikkben azt láttuk, hogy a hibernált tér tér sokkal egyszerűbbé teszi a térbeli adattípusok kezelését, mivel gondoskodik az alacsony szintű részletekről.

Annak ellenére, hogy ez a cikk a Mariadb4j fájlt használja, bármilyen konfiguráció módosítása nélkül lecserélhetjük MySql-re.

Mint mindig, a cikk teljes forráskódja megtalálható a GitHubon.