Úvod do režimu dlhodobého spánku
1. Úvod
V tomto článku sa pozrieme na priestorové rozšírenie hibernácie, hibernácie-priestorové.
Počnúc verziou 5, Hibernate Spatial poskytuje štandardné rozhranie pre prácu s geografickými údajmi.
2. Pozadie týkajúce sa režimu dlhodobého spánku
Geografické údaje zahŕňajú zastúpenie subjektov ako a Bod, čiara, mnohouholník. Takéto dátové typy nie sú súčasťou špecifikácie JDBC, a preto sa JTS (JTS Topology Suite) stal štandardom pre reprezentáciu typov priestorových údajov.
Hibernate spatial okrem JTS podporuje aj Geolatte-geom - nedávnu knižnicu, ktorá má niektoré funkcie, ktoré v JTS nie sú k dispozícii.
Obe knižnice sú už zahrnuté v hibernačno-priestorovom projekte. Používanie jednej knižnice nad druhou je jednoducho otázkou, z ktorej nádoby importujeme dátové typy.
Aj keď priestorový režim Hibernate podporuje rôzne databázy ako Oracle, MySQL, PostgreSQLql / PostGIS a niekoľko ďalších, podpora funkcií špecifických pre databázu nie je jednotná.
Je lepšie si prečítať najnovšiu dokumentáciu o režime spánku, aby ste skontrolovali zoznam funkcií, pre ktoré režim dlhodobého spánku poskytuje podporu pre danú databázu.
V tomto článku budeme používať pamäť Mariadb4j v pamäti, ktorá zachováva úplnú funkčnosť MySQL.
Konfigurácia pre Mariadb4j a MySql je podobná, dokonca aj knižnica mysql-connector funguje pre obe tieto databázy.
3. Maven závislosti
Pozrime sa na Mavenove závislosti potrebné na nastavenie jednoduchého priestorového projektu hibernácie:
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 prezimovať-priestorový závislosť je tá, ktorá poskytne podporu pre typy priestorových údajov. Najnovšie verzie hibernate-core, hibernate-spatial, mysql-connector-java a mariaDB4j je možné získať z Maven Central.
4. Konfigurácia priestorového režimu dlhodobého spánku
Prvým krokom je vytvorenie a prezimovať.vlastnosti v zdrojov adresár:
hibernate.dialect = org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect // ...
Jediná vec, ktorá je špecifická pre režim dlhodobého spánku, je MySQL56SpatialDialect nárečie. Tento dialekt rozširuje MySQL55Dialect a poskytuje ďalšie funkcie súvisiace s typmi priestorových údajov.
Kód špecifický pre načítanie súboru vlastností, vytvorenie a SessionFactorya inštancia inštancie Mariadb4j je rovnaká ako v štandardnom projekte hibernácie.
5. Pochopenie Geometria Typ
Geometria je základný typ pre všetky priestorové typy v JTS. To znamená, že iné typy majú radi Bod, Polygóna ďalšie siahajú od Geometria. The Geometria typ v jave zodpovedá GEOMETRIA zadajte aj MySql.
Analýzou a String reprezentácia typu, dostaneme inštanciu Geometria. Úžitková trieda WKTReader poskytnuté spoločnosťou JTS môžu byť použité na prevod akejkoľvek známej textovej reprezentácie na a Geometria typ:
public Geometry wktToGeometry (String wellKnownText) throws ParseException {return new WKTReader (). read (wellKnownText); }
Teraz sa pozrime na túto metódu v akcii:
@Test public void shouldConvertWktToGeometry () {Geometry geometry = wktToGeometry ("POINT (2 5)"); assertEquals ("Bod", geometry.getGeometryType ()); assertTrue (geometria instanceof Point); }
Ako vidíme, aj keď je návratový typ metódy čítať() metóda je Geometria, skutočný prípad je prípad a Bod.
6. Uloženie bodu do DB
Teraz, keď máme dobrú predstavu o tom, čo Geometria typ je a ako získať Bod z a String, poďme sa pozrieť na PointEntity:
@Entity verejná trieda PointEntity {@Id @GeneratedValue private Long id; súkromný bod bodu; // štandardné getre a setre}
Všimnite si, že entita PointEntity obsahuje priestorový typ Bod. Ako už bolo preukázané skôr, a Bod je reprezentovaná dvoma súradnicami:
public void insertPoint (reťazcový bod) {entita PointEntity = nová PointEntity (); entity.setPoint ((Point) wktToGeometry (point)); session.persist (entita); }
Metóda insertPoint () prijíma známu textovú (WKT) reprezentáciu a Bod, prevádza ho na a Bod napríklad a uloží do DB.
Pripomíname, že zasadanie nie je špecifický pre hibernáciu-priestorovú a je vytvorený podobným spôsobom ako v inom projekte hibernácie.
Môžeme si tu všimnúť, že akonáhle budeme mať inštanciu Bod proces ukladania PointEntity je podobný ako každý bežný subjekt.
Pozrime sa na niekoľko testov:
@Test public void shouldInsertAndSelectPoints () {PointEntity entity = new PointEntity (); entity.setPoint ((Point) wktToGeometry ("POINT (1 1)")); session.persist (entita); PointEntity fromDb = session .find (PointEntity.class, entity.getId ()); assertEquals ("POINT (1 1)", fromDb.getPoint (). toString ()); assertTrue (geometria instanceof Point); }
Telefonovanie natiahnuť() na a Bod vráti WKT reprezentáciu a Bod. Je to preto, lebo Geometria trieda prepíše natiahnuť() metóda a interne používa WKTWriter, bezplatná trieda do WKTReader ktoré sme videli skôr.
Po spustení tohto testu sa vytvorí režim dlhodobého spánku PointEntity stôl pre nás.
Pozrime sa na túto tabuľku:
desc PointEntity; Typ poľa Nulový identifikátor kľúča bigint (20) ŽIADNA geometria bodu PRI ÁNO
Podľa očakávania Typ z LúkaBod je GEOMETRIA. Z tohto dôvodu potrebujeme pri načítaní údajov pomocou nášho editora SQL (ako napríklad pracovný stôl MySql) previesť tento typ GEOMETRIE na text čitateľný človekom:
vyberte id, astext (bod) z PointEntity; id astext (bod) 1 BOD (2 4)
Pretože však hibernácia už vracia reprezentáciu WKT, keď voláme natiahnuť() metóda na Geometria alebo ktorejkoľvek z jeho podtried, s touto konverziou sa nemusíme trápiť.
7. Používanie priestorových funkcií
7.1. ST_WITHIN () Príklad
Teraz sa pozrieme na využitie databázových funkcií, ktoré pracujú s typmi priestorových údajov.
Jednou z takýchto funkcií v MySQL je ST_WITHIN () to hovorí, či jeden Geometria je v inom. Dobrým príkladom by tu bolo zistiť všetky body v danom okruhu.
Na úvod sa pozrieme na to, ako vytvoriť kruh:
verejná Geometry createCircle (dvojité x, dvojité y, dvojitý polomer) {GeometricShapeFactory shapeFactory = nový GeometricShapeFactory (); shapeFactory.setNumPoints (32); shapeFactory.setCentre (nová súradnica (x, y)); shapeFactory.setSize (polomer * 2); návrat shapeFactory.createCircle (); }
Kruh je reprezentovaný konečnou sadou bodov určených znakom setNumPoints () metóda. The polomer sa pred volaním na číslo zdvojnásobí setSize () metóda, pretože potrebujeme nakresliť kruh okolo stredu, v oboch smeroch.
Poďme teraz dopredu a pozrime sa, ako načítať body v rámci daného polomeru:
@ Test public void shouldSelectAllPointsWithinRadius () hodí ParseException {insertPoint ("POINT (1 1)"); insertPoint ("BOD (1 2)"); insertPoint ("BOD (3 4)"); insertPoint ("BOD (5 6)"); Dotaz na dotaz = session.createQuery ("vyberte p z PointEntity p, kde v rámci (p.point,: circle) = true", PointEntity.class); query.setParameter ("kruh", createCircle (0,0, 0,0, 5)); assertThat (query.getResultList (). stream () .map (p -> ((PointEntity) p) .getPoint (). toString ())) .containsOnly ("POINT (1 1)", "POINT (1 2)" "); }
Hibernácia mapuje svoje v rámci () funkcie do ST_WITHIN () funkcia MySql.
Zaujímavé je tu pozorovanie, že Bod (3, 4) padá presne na kruh. Dotaz však tento bod nevracia. To je preto, že the v rámci () funkcia vráti true iba ak je zadaná Geometria je úplne v inom Geometria.
7.2. ST_TOUCHES () Príklad
Tu uvedieme príklad, ktorý vloží množinu Polygóns v databáze a vyberte Polygóns ktoré susedia s daným Polygón. Poďme sa rýchlo pozrieť na PolygonEntity trieda:
@Entity verejná trieda PolygonEntity {@Id @GeneratedValue private Long id; súkromný polygón mnohouholník; // štandardné getre a setre}
Jediná vec odlišná od predchádzajúcej PointEntity je to, že používame typ Polygón namiesto Bod.
Poďme teraz k testu:
@Test public void shouldSelectAdjacentPolygons () hodí 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))"); Dotaz na dotaz = session.createQuery ("vyberte p z PolygonEntity p, kde sa dotkne (p.polygon,: polygon) = true", PolygonEntity.class); query.setParameter ("mnohouholník", wktToGeometry ("POLYGON ((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)) "," POLYGON ((3 0, 3 5, 8 5, 8 0, 3 0)) "); }
The insertPolygon () metóda je podobná insertPoint () metóda, ktorú sme videli skôr. Zdroj obsahuje úplnú implementáciu tejto metódy.
Používame dotyky () funkcia nájsť Polygóns susedí s daným Polygón. Jednoznačne tretí Polygón sa vo výsledku nevráti, pretože sa daný okraj nedotýka hrany Polygón.
8. Záver
V tomto článku sme videli, že hibernácia-priestorové zjednodušuje prácu s priestorovými dátovými typmi, pretože sa stará o detaily na nízkej úrovni.
Aj keď tento článok používa Mariadb4j, môžeme ho nahradiť MySql bez úpravy akejkoľvek konfigurácie.
Celý zdrojový kód tohto článku nájdete ako vždy na GitHub.