The most obvious answer is to use ST_AsGeoJSON to convert the geometry into a string on the database. However, this pushes some application logic into the database and, perhaps more importantly, it results in far more data being transferred over the network as the GeoJSON text representation is far less compact than the extended Well Known Binary (EWKB) that Postgres uses otherwise. It also means that you are unable to do anything useful in your MVC controllers with the geometry without deserialising it back to something like a JTS geometry.
A richer, and potentially faster (if there is networking involved), solution is to use spatial extensions for your JPA provider (eg Hibernate supports this out of the box in version 5, and had Hibernate-Spatial for version 4) to pull the geometry directly into your entity as a JTS (or similar) geometry. Most implementations will use WKB (Well Known Binary) as a compact representation over the wire, then deserialise into the appropriate Java type, rather than converting every 64bit (8 bytes) binary double into some huge structure! With Hibernate one can do the following (adjust definition as required for SRID and geometry type etc):
@Column(columnDefinition = "geometry(MultiPolygon,4326)")
private Geometry geom;
Then tell Spring that you are using the PostGIS dialect in application.properties (or other config source):
spring.jpa.database-platform=org.hibernate.spatial.dialect.postgis.PostgisDialect
Your Spring data repositories will now return entities with geometries (it's also possible to write JPQL queries on the repository interface methods to support spatial queries, eg bounding box intersection etc).
Having got an entity with a populated geometry you can easily convert this to GeoJSON with Jackson on your endpoints by including converters for the JTS types in your build, eg https://github.com/bedatadriven/jackson-datatype-jts:
<dependency>
<groupId>com.bedatadriven</groupId>
<artifactId>jackson-datatype-jts</artifactId>
<version>2.2</version>
</dependency>
and then adding it to the Jackson ObjectMappers created by Spring by creating a suitable bean in one of your application configuration classes, eg:
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.modulesToInstall(new JtsModule());
return builder;
}
You may need more configuration of Jackson than this for other things (null handling, indentation, etc) but it's a good start.
Now, when you return a JTS geometry on an object from your Spring MVC controllers they will automatically be converted to GeoJSON geometries. You will have to either replicate GeoJSON Feature / FeatureCollection structures as classes if you want to use those, or return something (eg your Entity) that can be easily mapped in JavaScript into such a structure.