我正在创建一个使用一些空间查询的项目。我使用带有Spring数据存储库的Spring引导和带有PostGIS扩展的PostgreSQL作为数据库。
我创建了这个存储库:
import com.vividsolutions.jts.geom.Geometry;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface AreaRepository extends CrudRepository<Area, Long> {
/*
extra queries for Area here
*/
@Query(value="select st_intersection(" +
":base_layer ," +
":filter_layer" +
")", nativeQuery = true)
Geometry geometryIntersectGeometry(@Param("base_layer") Geometry baseGeometry,@Param("filter_layer") Geometry filterGeometry);
}
它包含对Area实体的一些查询。我还想使用一些PostGIS函数来进行一些计算,所以我创建了geometryIntersectGeometry来从PostGis调用st_intersection函数,这应该返回一个几何。
我在设置中将hibernate方言设置为PostGIS:
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/test_db
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.properties.hibernate.dialect = org.hibernate.spatial.dialect.postgis.PostgisDialect
我有hibernate空间的依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-spatial</artifactId>
<version>${hibernate.version}</version>
</dependency>
...
调用geometryIntersectGeometry函数会导致错误:
No Dialect mapping for JDBC type: 1111; nested exception is org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111,{}
如何告诉JPA / Spring Data将几何(PostGIS类型)响应映射到Geometry(com.vividsolutions.jts.geom.Geometry)对象?
你添加了Hibernate Spatial吗?
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-spatial</artifactId>
<version>${hibernate.version}</version>
</dependency>
这支持GIS数据:http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#spatial
管理通过编写存储库的custom implementation来修复它并注册类型(thx Simon Martinelli)
库:
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface AreaRepository extends CrudRepository<Area, Long>, AreaGisRepository {
/*
extra queries for Area here
*/
}
接口:
import com.vividsolutions.jts.geom.Geometry;
public interface AreaGisRepository {
Geometry geometryIntersectGeometry(Geometry baseGeometry, Geometry filterGeometry);
}
和实施:
import com.vividsolutions.jts.geom.Geometry;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor;
import org.springframework.beans.factory.annotation.Autowired;
import javax.persistence.EntityManager;
public class AreaGisRepositoryImpl implements AreaGisRepository {
private EntityManager entityManager;
@Autowired
public AreaGisRepositoryImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Override
public Geometry geometryIntersectGeometry(Geometry baseGeometry, Geometry filterGeometry) {
return (Geometry) entityManager
.createNativeQuery(
"select st_intersection(:base_layer , :filter_layer) as geom")
.setParameter("base_layer", baseGeometry)
.setParameter("filter_layer", filterGeometry)
.unwrap(org.hibernate.query.NativeQuery.class)
.addScalar("geom", new JTSGeometryType(PGGeometryTypeDescriptor.INSTANCE))
.getSingleResult();
}
}
它工作得很完美,但我现在对Postgis有一个硬编码依赖(不太可能我们会使用其他东西,但......)
我认为有一种更简单的方法可以完成这项工作。 Hibernate Spatial注册了许多空间函数,以便在HQL / JQL中使用。所以以下应该有效
@Query(value="select intersection(" +
":base_layer ," +
":filter_layer" +
")")
Geometry geometryIntersectGeometry(@Param("base_layer") Geometry baseGeometry,@Param("filter_layer") Geometry filterGeometry);
有关Spatial Dialects中可用功能的列表,请参阅documentation。