H2GIS 포스팅
팀프로젝트를 하는중 위도와 경도로 표현된 두 점 사이의 거리가 주어진 거리 보다 가까운 데이터를 추출해야 하는 문제에 부딪혔다.
처음엔 두 점 사이의 공식 sqrt((x2 - x1)^2 + (Y2 - y1)^2)를 이용해서 구했다.
그런데 위도 경도는 평면이 아닌 3차원의 구면을 이용한 좌표계이다.
이제부터 PostGIS를 컨테이너로 띄워서 Spring Dtat JPA에서 위도와 경도를 이용해 범위 내 위치한 데이터를 찾는 방법을 기술하겠다.
postgis
위키
- 객체 관계형 데이터베이스에 지리 객체에 대한 지원을 추가하는 오픈 소스 소프트웨어 프로그램
- PostGIS는 PostgreSQL 외부 확장 으로 구현
postgis 컨테이너 실행
postgis image
postgis 이미지를 다운받는다
- docker pull postgis/postgis
도커 컨테이너를 실행한다
- docker run --platform linux/amd64 --name some-postgis -p 5432:5432 -e POSTGRES_PASSWORD=mysecretpassword -d postgis/postgis
- --platform linux/amd64: mac M1이라서 아키텍처를 지정함
- --name: 컨테이너 이름
- -p: 바인딩 포트
- -e: 환경변수
- -d: 백그라운드 실행
- postgis/postgis: 이미지 이름
psql을 통해 databse를 생성한다.
- docker exec -it postgres bash
- psql -U postgres
- create database name
postgis 확장 모듈을 설치한다
생성한 데이터베이스에서 확장 모듈을 설치한다
- CREATE EXTENSION postgis;
생성된 databse의 Schemas/public/Functions에 추가된 postgis 함수를 볼 수 있다.
내가 봤던 블로그에서는 없는 함수를 사용하는경우가 종종 있어서 함수는 공식문서를 참고하길 추천한다.
한 점은 geometry(Point, 4326) 타입이다.
docker-compose
docker-compose
환경변수에 확장 모듈을 추가해줬다
- POSTGRES_MULTIPLE_EXTENSIONS: postgis,hstore,postgis_topology,postgis_raster,pgrouting
Hibernate Spatial
Hibernate Spatial
- Hibernate Spatial은 지리적 데이터를 처리하기 위해 Hibernate에 대한 확장으로 개발되었습니다
- 5.0부터 Hibernate Spatial은 Hibernate ORM 프로젝트의 일부입니다.
- Hibernate Spatial은 지리적 데이터 저장 및 쿼리 기능에 대한 표준화된 교차 데이터베이스 인터페이스를 제공합니다.
- 지원되는 데이터베이스는 Oracle 10g/11g, PostgreSql/PostGIS, MySQL, Microsoft SQL Server 및 H2/GeoDB입니다.
Hibernate Spatial 의존성 추가한다
Hibernate Spatial
이제 모든 준비가 끝났다.
참고로 다른 블로그에서 dialect를 추가하라고 하는데
- org.hibernate.spatial.dialect.postgis.PostgisDialect
절대 추가하면 안된다. deprecated 되어서 추가하면 에러만 발생한다. 실행하면 로그를 통해 자동으로 dialect가 추가되는걸 확인할 수 있다.
jpql쿼리로 postgis함수를 통해 거리계산을 해보겠다
st_dwithin
4개의 매개변수는 차례대로 좌표1, 좌표2, 거리, 타원체
로써 좌표1 과 좌표2가 거리(meter) 안에 있으면 true를 반환한다. 마지막 4번째 매개변수는 true는 타원체, false는 구체로 타원체보다 더 빠르게 계산한다.
Point 객체 생성
point class
- org.locationtech.jts.geom.Point 타입이다.
- 매개변수가 없는 Precision Model 생성자는 기본 정밀도가 FLOOTING이다
- srid 4326은 세계 지구 좌표 시스템(WGS84) 뜻한다.