
O PostGIS é um software de código aberto que adiciona suporte a recursos geográficos ao banco de dados relacional do PostgreSQL.
Este breve artigo discutirá seu uso em Java. Em particular, a tarefa de encontrar objetos geográficos por suas coordenadas.
O PostGIS foi criado em 2001. É uma boa solução gratuita para armazenar dados de mapas no banco de dados. Mas o artigo não é inteiramente sobre ele, mas apenas sobre um caso especial - trabalho conveniente com o PostGIS usando ferramentas JPA.
Dependências
As seguintes bibliotecas são importantes para nossa tarefa:
- Hibernate 5.3.7
- hibernate-space - mesma versão. Teoricamente, você pode usar os mais antigos. A partir do quinto, hibernar-espacial é o mesmo que hibernar. Anteriormente: Hibernate Spatial 1.1.x para o Hibernate 3.6.x, Hibernate Spatial 1.0 para o Hibernate 3.2.x - 3.5.x.
- postgresql 42.2.4. Esta versão foi adotada, porque as mais novas reforçavam os requisitos de SSL. Escolha a versão do driver que corresponde à versão do banco de dados.
Bem, tudo que você precisa para o JPA é Spring ou um contêiner.
Dialetos
O Hibernate Spatial fornece
abstrações geométricas para trabalhar com bases espaciais. Como no JPA, como primeira aproximação, não estamos interessados em qual banco de dados é usado no servidor.
Oficialmente suportado pelo PostgresSQL, Oracle, MySQL, MS SQLServer, GeoDB (H2), DB2.
Apresenta detalhes de suporte . Músculo pode parecer um estranho. Mas na versão 8, o suporte a dados espaciais é decentemente
aprimorado .
Nós usamos o Postgres. Mas você precisa especificar o dialeto Hibernate
"org.hibernate.spatial.dialect.postgis.PostgisDialect"
vez do padrão pós-grego.
Está na hora de codificar
Uma tabela no PostGIS pode ter qualquer campo. Apenas padrão, um deles será do tipo geometria. E há geografia (não suportada agora no Hibernate). Se você não ensinar Java a trabalhar com esse tipo, ele será interpretado como um blob ou String no formato "01010000207B7F0000188D594CC9B22541BC4E56674F2C5541".
Obviamente, você pode trabalhar com o PostGis em um JBDC puro.
Um exemplo Mas isso requer um trabalho minucioso separado com
org.postgis.PGgeometry
. Essas não são as classes que o artigo tratará. E não haverá mais tolerância.
Vamos ao JPA e criamos uma classe simples:
@Entity public class AdressBuilding implements Serializable { @Id private Integer id; private Point geom; ...
Os campos restantes são omitidos (um objeto geográfico pode armazenar qualquer informação). Nada incomum aqui - a classe de entidade padrão. Apenas um objeto da classe Point é interessante - um ponto do espaço tridimensional.
A seguir, as classes do pacote com.vividsolutions.jts.geom são usadas.
O JTS se tornou o padrão de fato para representar dados geoespaciais. Ele implementa a especificação Simple Feature Specification /
Simple Feature Access criada pelo OpenGIS nos anos 90.
Esclarecimento . O ponto é herdado da classe Geometry abstrata. Ele contém os seguintes campos não estáticos:
protected Envelope envelope; protected final GeometryFactory factory; protected int SRID; private Object userData;
Envelope é a caixa delimitadora mínima para essa geometria. Mas pode voltar na forma de geometria. E então você terá uma tentativa interminável de serialização.
SRID - número do sistema de coordenadas. Existem muitos deles. As principais diferenças: o formato das coordenadas (metros, graus ...), o ponto de referência e a forma da Terra (a Terra não é redonda). O PostGis conhece muitos sistemas de coordenadas e pode transformá-los.
Como eu disse, temos um tipo de geometria no banco de dados. Eu imediatamente usei a classe Point concreta por conveniência, porque nesta tabela eu tenho apenas objetos point. Mas o PostGIS teórico pode armazenar vários tipos de geometria ao mesmo tempo. Apenas em cada geometria, seu tipo é indicado:
"geometry":{"type":"MultiPolygon","coordinates":...
De acordo com o StackOverflow, o uso de várias geometrias na mesma tabela reduz a velocidade das consultas. Geometrias também podem ser aninhadas. Tipos:

Consultas de banco de dados
Com a implementação da classe resolvida. agora é hora de tirá-los da base. Nossos pontos são casas, ou melhor, seus endereços. Você pode fazer consultas SQL familiares: obter casas por ID, número, número de avós ...
Agora estamos interessados em consultas espaciais. Por exemplo, encontre uma casa por coordenadas. Deixe as coordenadas desejadas x, ye + + delta ser a área de pesquisa desejada. As principais consultas no STS são realizadas na proporção de geometrias. Portanto, precisamos criá-lo:
Coordinate c1 = new Coordinate(x - delta, y - delta); ... Coordinate[] coordinates = new Coordinate[]{c1, c2, c3, c4, c1}; GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();
Se não especificarmos um sistema de coordenadas, o PostGis se recusará a compará-los. Você conhece o código do sistema ou o obtém de qualquer lugar com o código
.getGeom().getSRID()
.
Em seguida, enviamos uma solicitação do formulário:
"select a " + "from AdressBuilding a " + "where within(a.geom, :window) = true"
Uma consulta dentro significa verificar se a geometria está dentro de outra. Não se assuste se o seu IDE disser que não pode haver tal solicitação na JPA. O Hibernate Spatial o converte em:
where st_within(adressbuil0_.geom, ?)=true
Onde
st_within
já é uma função PostGis.
Existem várias opções para obter o mesmo resultado - o ponto caiu em um quadrado.
contains(:window, a.geom) / intersects(a.geom, :window)...

Uma descrição detalhada das especificações está
aqui .
Posfácio
Temos os pontos - agora faça o que quiser com eles.
Testei o caso de um pequeno banco de dados em um servidor com uma quantidade relativamente grande de RAM. Se você carregar ao máximo e esquecer os índices, a tarefa de pesquisa será executada no processador.
O Postgres possui muitos índices diferentes.
E alguns deles ajudam o Postgis . O estudo mostrou que apenas GIST (?) É adequado para
pontos CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] );
Porém, na maioria das vezes, quando você importa dados para o PostGis, os índices são criados automaticamente ...
Esclarecimentos e informações adicionais são bem-vindos.
Manual utilizado:
For hibernate 5For hibernate 4