Hibernate 5.1 + Vertica Spatial Объединяем все вместе

Ошибка:

com.vertica.support.exceptions.DataException: [Vertica]VJDBC ERROR: невозможно напрямую ВСТАВИТЬ или КОПИРОВАТЬ пользовательские типы. Пожалуйста, вычислите их, используя соответствующие пользовательские функции.

Мой текущий диалект

public class VerticaDialect extends org.hibernate.spatial.dialect.postgis.PostgisDialect {

private static final String SELECT_LAST_INSERT_ID = "SELECT LAST_INSERT_ID()";

@Override
public IdentityColumnSupport getIdentityColumnSupport() {

    return new IdentityColumnSupport() {
        ...
        @Override
        public String getIdentitySelectString(String arg0, String arg1, int arg2) throws MappingException {
            return SELECT_LAST_INSERT_ID;
        }
        ...
    };
}

}

Мои зависимости

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.1.1.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>5.1.1.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-spatial</artifactId>
     <version>5.1.1.Final</version>
</dependency>
<dependency>
    <groupId>javax.persistence</groupId>
    <artifactId>persistence-api</artifactId>
    <version>1.0</version>
</dependency>

My Vertica table

alter table something add GIS_WGS84 GEOGRAPHY NULL;

Моя модель

import org.geolatte.geom.C2D;
import org.geolatte.geom.G2D;
import org.geolatte.geom.Polygon;

@Column(name="gis_wgs84")
public Polygon<G2D> getGisWGS84() {
    return gisWGS84;
}

public void setGisWGS84(Polygon<G2D> gisWGS84) {
    this.gisWGS84 = gisWGS84;
}

Мой тест

Geographic2DCoordinateReferenceSystem wgs84 = CrsRegistry.getGeographicCoordinateReferenceSystemForEPSG(4326); // G2D

PositionSequence<G2D> wgs84positionSequence = 
                PositionSequenceBuilders.fixedSized(5, G2D.class)
                .add(new G2D(30.0, 60.0))
                .add(new G2D(30.0, 61.0))
                .add(new G2D(31.0, 61.0))
                .add(new G2D(31.0, 60.0))
                .add(new G2D(30.0, 60.0))
                .toPositionSequence();
Polygon<G2D> wgs84poly = new Polygon<>(wgs84positionSequence, wgs84);
something.setGisWGS84(wgs84poly);

Мои вопросы:

  • Должен ли я использовать org.geolatte.geom.Polygon или что-то еще? Существует также этот пакет com.vividsolutions.jts.geom. Я смущен. Hibernate ORM документация бесполезна; он упоминает оба, и пример не показывает импорт.
  • Должен ли я переопределить диалект Postgis? Vertica загружает данные с помощью функции ST_GeographyFromText('LINESTRING(-42.0 23.0, -62.0 23.0)')

person Esko Piirainen    schedule 30.08.2016    source источник


Ответы (2)


Ваша модель и тестовый код в порядке. Документация Hibernate ORM объясняет, почему существуют две модели Geometry (JTS и Geolatte) в разделе 18.1. Вы можете выбрать любой из них.

Проблема в вашем Vertica Dialect. Есть еще кое-что в реализации диалекта Vertica Spatial. Hibernate Spatial необходимо сериализовать пространственный объект Java в формат, специфичный для базы данных. Однако Hibernate Spatial в настоящее время не знает, как это сделать для базы данных Vertica.

person Karel Maesen    schedule 30.08.2016
comment
Спасибо за ответ! Я переопределяю Hibernate Postgis -dialect, и Vertica должна иметь ту же функцию ST_GeographyFromText(?), что и PostGIS: postgis.net/docs/manual-2.2/ .. ? - person Esko Piirainen; 30.08.2016
comment
Это не то, как работает Hibernate Spatial. Он работает путем прямой сериализации объектов геометрии Java (JTS или Geolatte) в собственный двоичный формат базы данных. Он не проходит ни через какие функции преобразования st_* - person Karel Maesen; 31.08.2016
comment
Хорошо .. Если вы хотите указать мне функции диалекта, которые мне нужно переопределить, я бы счел это принятым ответом :) Но я тоже начну искать API. - person Esko Piirainen; 01.09.2016

Переопределение диалекта было бы довольно сложной задачей, поэтому мы решили загрузить данные геометрии как WKT, а затем, после того как все строки вставлены в Vertica, вызвали новое обновление вставленных строк, которое заполняет столбцы Geometry/Geography.

Что-то вроде этого:

session.createQuery(sql)
    .setParameterList("documentKeys", documentKeys)
    .executeUpdate();
}

 UPDATE tablename  
 SET    wgs84_geo = public.ST_GeographyFromText(wgs84_wkt) 
 WHERE  document_key IN (:documentKeys)

Плохо то, что в Vertica обновление — это новое удаление + вставка, но для производительности запросов лучше иметь их в той же таблице, что и остальные данные.

«К счастью», потом мы обнаружили, что Vertica не поддерживает запросы для мультиполигонов, которые у нас есть, поэтому нам пришлось переместить столбцы Geometry/Geography из основной таблицы в виде связанных таблиц, содержащих по одной строке для каждого полигона мультиполигона. Эти связанные таблицы присоединяются к основной таблице для запросов, когда требуется поиск по географии. Что получается для нас недостаточно быстро... Но, по крайней мере, нам больше не нужно делать вставку + обновление в основной таблице.

person Esko Piirainen    schedule 18.08.2017