Моя цель — добавить возможность геопространственных запросов в мой проект Spring Boot + MySql, сгенерированный jhipster, но мне не удалось правильно настроить мою базу данных H2 для запросов, выполняемых моими тестами, и моей базой данных разработчиков для локального развертывания приложения. Поскольку у нас есть строгий конвейер CI/CD, это означает, что я еще не смог протестировать в prod, но подозреваю, что и там столкнусь с той же ошибкой. Ошибка, которую я получаю при выполнении пространственного запроса в тестовой среде или среде разработки: org.h2.jdbc.JdbcSQLSyntaxErrorException: Function "WITHIN" not found;
.
Есть несколько сообщений и руководств, посвященных этой проблеме, но они не решили проблему для меня. Я следовал руководству здесь, полезной документации здесь и попробовал решения/предложения в сообщение 1, пост 2, post 3, post 4 и некоторые другие. Я также сравнил свой код с этим примером проекта. Но я все еще не могу пройти мимо этой ошибки.
Соответствующая конфигурация... pom.xml:
...
<java.version>1.8</java.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
<spring.version>5.1.8.RELEASE</spring.version>
<hibernate.version>5.3.10.Final</hibernate.version>
<h2.version>1.4.199</h2.version>
<jts.version>1.13</jts.version>
...
<repositories>
<repository>
<id>OSGEO GeoTools repo</id>
<url>http://download.osgeo.org/webdav/geotools</url>
</repository>
<repository>
<id>Hibernate Spatial repo</id>
<url>http://www.hibernatespatial.org/repository</url>
</repository>
</repositories>
...
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-spatial</artifactId>
</dependency>
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>${jts.version}</version>
</dependency>
</dependencies>
Мой главный application.yml
:
spring:
jpa:
open-in-view: false
properties:
hibernate.jdbc.time_zone: UTC
hibernate:
dialect: org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect
ddl-auto: none
Мой application-dev.yml
для моей среды разработки:
spring:
h2:
console:
enabled: false
jpa:
database-platform: org.hibernate.spatial.dialect.h2geodb.GeoDBDialect
database: H2
show-sql: true
hibernate:
dialect: org.hibernate.spatial.dialect.h2geodb.GeoDBDialect
Мой application-prod.yml
для продукта:
spring:
jpa:
database-platform: org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect
database: MYSQL
show-sql: false
My test/application.yml
:
spring:
jpa:
database-platform: org.hibernate.spatial.dialect.h2geodb.GeoDBDialect
database: H2
open-in-view: false
show-sql: false
hibernate:
dialect: org.hibernate.spatial.dialect.h2geodb.GeoDBDialect
ddl-auto: none
Соответствующий код на сервисном уровне:
@Override
@Transactional(readOnly = true)
public Page<MyObject> findAllWithinDistanceOfLocation(Float distance, Point location, Pageable pageable) {
log.debug("Request to get all MyObject within a distance centered on location");
GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
shapeFactory.setNumPoints(32); // 32 = number of points to define circle. Default is 100. Higher the number, the more accurately drawn the circle
shapeFactory.setCentre(location.getCoordinate());
shapeFactory.setSize(distance * 2);
Geometry areaOfInterest = shapeFactory.createCircle();
return myObjectRepository.findAllWithinCircle(areaOfInterest, pageable);
}
Соответствующий код в репозитории:
@Query("select e from MyObjectTable e where within(e.location, :areaOfInterest) = true")
Page<MyObject> findAllWithinCircle(@Param("areaOfInterest") Geometry areaOfInterest, Pageable pageable);
Соответствующий код в компоненте конфигурации базы данных:
/**
* Open the TCP port for the H2 database, so it is available remotely.
*
* @return the H2 database TCP server.
* @throws SQLException if the server failed to start.
*/
@Bean(initMethod = "start", destroyMethod = "stop")
@Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
public Object h2TCPServer() throws SQLException {
String port = getValidPortForH2();
log.debug("H2 database is available on port {}", port);
return H2ConfigurationHelper.createServer(port);
}
private String getValidPortForH2() {
int port = Integer.parseInt(env.getProperty("server.port"));
if (port < 10000) {
port = 10000 + port;
} else {
if (port < 63536) {
port = port + 2000;
} else {
port = port - 2000;
}
}
return String.valueOf(port);
}
Я пробовал разные значения для вышеперечисленных свойств, пытаясь сделать это принципиальным образом на основе документации и других проектов, но, похоже, я не могу заставить это работать должным образом. Я подозреваю, что мне не хватает команды начальной настройки h2, которая создает псевдоним для WITHIN
, но до сих пор не смог ее найти и заставить это работать.
Примечание. Я включил и исключил указанный выше раздел файла pom безрезультатно.