Skip to content

PostGIS with Java JPA and Hibernate

Ricardo Campos edited this page May 17, 2024 · 5 revisions

How to work with PostGIS in Java

This page contains steps and code samples to get you started with PostgreSQL + the PostGIS Extension, and additionally, provides Java integration with Hibernate and JPA.

The basics - Database

  • PostGIS Docker Image: We have postgis/postgis:15-master
  • Enable PostGIS extension: The extension is actually enabled once you get the postgis image. However, you may like to enable the pgcrypto extension on the database startup. For that (add on your Dockerfile):
RUN sed -i '/EXISTS postgis_tiger_geocoder;*/a CREATE EXTENSION IF NOT EXISTS pgcrypto;' \
        /docker-entrypoint-initdb.d/10_postgis.sh

The basics - Java with Maven

  • Add Hibernate Spatial dependency: Update the project pom.xml file:
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-spatial</artifactId>
  <version>${hibernate.version}</version>
</dependency>
  • PostreSQL JPA Dialect: Update the project application.properties file, if needed:
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

That's it! Now you should be able to work with Point, Geometry and other formats out-of-the-box easily with Java and PostGIS.

Code samples

Entity Java class:

import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;

@Entity
@Table(name = "my_table")
public class MyClass {
  
  /* 2D or 3D Points */
  @Column(name = "mean_geom")
  private Point meanGeom;

  /* Geometry, polygon, areas */
  @Column(name = "area_geom")
  private Geometry myGeometry;
}

Repository Java class:

  • No changes required. Works just fine!

Creating a 2D or 3D point:

/* Imports */
import java.math.BigDecimal;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.PrecisionModel;

/* The GeometryFactory class provides different PrecisionModels. You can make the SRID explicit if you want. */
GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(PrecisionModel.FIXED), 4326);

/* Coordinate expects to receive a 'double' value. You can work with BigDecimal and then call the doubleValue() method. */
/* For a 2D point, just remove the third parameter */
Coordinate coordinate = new Coordinate(49.11941257871176, -122.83461402566606, 3.4D);

/* Create the Point instance */
Point point = geometryFactory.createPoint(coordinate);

/* Set on your entity object instance */
seedlot.setMeanGeom(point);

/* Then if you need to get the values later, here's how you can do */
Coordinate myPoint = seedlot.getCoordinate();

/* Then just call: */
double x = myPoint.getX();
double y = myPoint.getY();
double z = myPoint.getZ();

/* For BigDecimal */
BigDecimal x = new BigDecimal(String.valueOf(StringmyPoint.getX()));
BigDecimal y = new BigDecimal(String.valueOf(StringmyPoint.getY()));
BigDecimal z = new BigDecimal(String.valueOf(StringmyPoint.getZ()));

Here's how a Point gets stored on the database: image

Notes

  • No wrap or unwrap methods are needed (marshall and unmarshall). Hibernate dependency handles everything :)
  • Geometry types were not covered here, but you can explore methods by yourself. Just deep dive into the GeometryFactory Java class.

GraalVM and Cloud-native image

  • Hibernate Spatial is currently NOT fully supported out of the box. You DO need to twik a bit.
  • You need to register a RuntimeHint that will be initializing Spatial Logger classes.
  • Here's SPAR configuration (feel free to copy): HibernateSpatialCloudNativeConfig

Rerefences

Indirectly related:

Clone this wiki locally