Integrate Spring Boot and PostGIS to manage spatial data
In this post, I will show you how we can manage spatial data using Spring Boot and PostGIS.
Spatial data are useful when we would like to develop Geographic Information System or any application that needs to deal with a Map.
What is PostGIS?
PostGIS is an extension of Postgres to help you manage spatial data. PostGIS provides the types (Point, Line, Polygon) and a set of useful functions to manipulate those data. In this tutorial, I will be using the ST_DistanceSphere function to get all the cities within a given distance from a point. You can refer to PostGIS documentation to know more about the available functions: http://www.postgis.org/docs/ST_Distance_Sphere.html
These functions can be used in your SQL queries like any other SQL function.
Let’s jump to the code and write our app !
Run PostGIS
For this tutorial, we will need to install PostGIS database.
We will use Docker and docker-compose command line to run PostGIS.
docker-compose up -d
The docker-compose.yaml is provided in the git repository.
Create a Spring Boot project
The fastest way to create a new project is to use Spring Initialzr website.
On the right, you will have to select all the dependencies that you would like to include in your project and click “Generate” to get the ZIP file containing your project.
Configure Spring Boot
Unzip the archive, go to the root folder of the new project and use your favorite IDE to edit the code.
- Configure the datasource and PostGIS dialect in the src/main/resources/application.yaml file
server:
port: 8980spring:
# Database configuration
datasource:
driverClassName: org.postgresql.Driver
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5435}/${DB_NAME:postgis}
username: ${DB_USER:postgis}
password: ${DB_PASSWORD:postgis
# JPA configuration
jpa:
# PotGIS configuration
database-platform: org.hibernate.spatial.dialect.postgis.PostgisDialect
hibernate:
ddl-auto: update
show-sql: true
database: postgresql
2. Add hibernate spatial support to your project
<dependency>
<groupId>com.bedatadriven</groupId>
<artifactId>jackson-datatype-jts</artifactId>
<version>${jackson.jts.version}</version>
</dependency><dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts-core</artifactId>
<version>${jts.version}</version>
</dependency><dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-spatial</artifactId>
<version>${hibernate.version}</version>
</dependency>
Notes: I had to downgrade hibernate spatial version due to some recent changes in the jts-core library. See more here: https://stackoverflow.com/questions/48946230/java-io-streamcorruptedexception-invalid-stream-header-30313031
3. Build
mvn clean install
Importing Spatial data
We will be using some OpenSource representing US cities with their population and elevation.
https://github.com/giswqs/data/blob/main/us/us_cities.geojson
The data is in GeoJSON format and needs to be imported to PostGIS.
We can use the ogr2ogr command line to import GeoJSON to our database but I will show you another way using a more friendly tool called QGIS.
QGIS is a user friendly Open Source Geographic Information System (GIS) licensed under the GNU General Public License. QGIS is an official project of the Open Source Geospatial Foundation (OSGeo)
Now that we have our new data in PostGIS, we can start to code our Spring Boot application.
Serialisation/Deserialisation of JTS data types
Add the JTS module for Serialisation/DeSerialisation of geometries. You can add this bean in a separate @Congiguration or directly in your application.
Spatial Entity
Create the entity with the PostGIS geometry attribute. This entity will do the mapping between the java attributes and the database table and columns.
Note: The ` are used to tell Postgres to be case sensitive for the column name. If you don’t add them, the query will fail because JPA will look at the column name in lowercase.
Repository
The repository will be the simplest as possible and will find cities around a point within a given distance in meter.
Controller
The controller exposes 2 endpoints:
Run the project
mvn spring-boot:run
- http://localhost:8980/city?page=1&size=10 to fetch the cities in a page
- http://localhost:8980/city/lat/lon/distance to get the cities around a geographical position
That’s it!
I hope you learnt something new in this tutorial. You can find the git repository here: https://github.com/nouhouari/spring-boot-postgis
Happy learning!
Where to go from here?
- Add geographical index to speed up the query time
- Use specification to mix spatial and non spatial column in the query