示例代码:https://github.com/bigben0123/spring-boot-spatial-example
1,配置application.properties
#sqlserver configure
spring.datasource.url =jdbc:sqlserver://localhost:1433;DatabaseName=myDatabase
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.driverClassName =com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.database=SQLSERVER
spring.jpa.properties.hibernate.default_schema=dbo
#database name
spring.jpa.properties.hibernate.default_catalog=myDatabase
#使用空间数据类型 geometry等,需要把方言改成:spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServer2008Dialect # Naming strategy spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy spring.jpa.hibernate.ddl-auto=create-drop #spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.h2geodb.GeoDBDialect #spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.mysql.MySQL56InnoDBSpatialDialect spring.jpa.show-sql=true spring.datasource.platform=mysql logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE logging.level.org.hibernate.type=TRACE
2, 在maven中添加sql server的jdbc驱动包
官网下载sqljdbc4的jar包
解压到任意位置(win:E:sqljdbc_6.0chsjre8)。在有sqljdbc4.jar包的文件夹下,通过shift+右键的方式–>此处打开命令窗口,然后执行以下maven命令:
mvn install:install-file -DgroupId=com.microsoft.sqlserver -DartifactId=sqljdbc4 -Dversion=4.2 -Dpackaging=jar -Dfile=E:sqljdbc_6.0chsjre8sqljdbc42.jar
显示build success,mvn库文件会放在C:UsersAdministrator.m2 epositorycommicrosoftsqlserver
3,pom.xml中添加依赖
<!-- sqlserver connector -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<scope>4.2</scope>
<version>4.2</version>
</dependency>
____________________________________________________________________________________________________
源码参考:
super entity:
package org.vaadin.example; import java.io.Serializable; import java.util.Objects; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass; import javax.persistence.Version; /** * * @author Matti Tahvonen */ @MappedSuperclass public abstract class AbstractEntity implements Serializable, Cloneable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Version private int version; public Long getId() { return id; } protected void setId(Long id) { this.id = id; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if(this.id == null) { return false; } if (obj instanceof AbstractEntity && obj.getClass().equals(getClass())) { return this.id.equals(((AbstractEntity) obj).id); } return false; } @Override public int hashCode() { int hash = 5; hash = 43 * hash + Objects.hashCode(this.id); return hash; } }
package org.vaadin.example; import java.util.Date; import javax.persistence.Entity; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Point; import javax.persistence.Column; import javax.persistence.Temporal; import javax.persistence.TemporalType; @Entity public class SpatialEvent extends AbstractEntity { private String title; @Temporal(TemporalType.DATE) private Date date; //@Column(columnDefinition = "POINT") // this type is known by MySQL @Column(columnDefinition = "geometry") private Point location; // @Column(columnDefinition = "POLYGON") // this type is known by MySQL @Column(columnDefinition = "geometry") private LineString route; public SpatialEvent() { } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public LineString getRoute() { return route; } public void setRoute(LineString route) { this.route = route; } public Point getLocation() { return location; } public void setLocation(Point location) { this.location = location; } }
package org.vaadin.example; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.transaction.annotation.Transactional; /** * @author mstahv */ public interface SpatialEventRepository extends JpaQueryDslPredicateRepository<SpatialEvent, Long> { }
主代码:
package org.vaadin.example; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import java.util.Date; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class SpatialSpringBootAppApplication { public static void main(String[] args) { SpringApplication.run(SpatialSpringBootAppApplication.class, args); } @Bean CommandLineRunner init(SpatialEventRepository repo,SimpleEventRepository repo1) { return (String... strings) -> { GeometryFactory factory = new GeometryFactory(); // repo.insert(23, 61); SpatialEvent theEvent = new SpatialEvent(); theEvent.setTitle("Example event"); theEvent.setDate(new Date()); theEvent.setLocation(factory.createPoint(new Coordinate(26, 62))); theEvent.getLocation().setSRID(4326); repo.save(theEvent); SpatialEvent eventWithPath = new SpatialEvent(); Coordinate[] coords = new Coordinate[] { new Coordinate(22, 60), new Coordinate(23, 61), new Coordinate(22, 63) }; eventWithPath.setRoute(factory.createLineString(coords)); eventWithPath.getRoute().setSRID(4326); eventWithPath.setLocation(factory.createPoint(new Coordinate(22, 60))); eventWithPath.getLocation().setSRID(4326); eventWithPath.setDate(new Date()); eventWithPath.setTitle("MTB cup 1/10"); repo.save(eventWithPath); }; } }
计算距离:
select location.ToString(),version, geography::STGeomFromText(location.ToString(), 4326).STDistance(geography::STGeomFromText('POINT(22 60)', 4326)) from spatial_event
5公里以内:
select * from spatial_event where geography::STGeomFromText(location.ToString(), 4326).STDistance(geography::STGeomFromText('POINT(22 60)', 4326))<5000
注意:
sqlserver的java类与数据库名称对应:MyDatabase 对应 my_database
sqlserver 用原生sql语句时,需要写完整的表名:数据库.dbo.表名
String sql = "select * from mydb.dbo.mytable" +" where location.STDistance('POINT(-121.626 47.8315)')<5"; Query query = em.createNativeQuery(sql); // query.setParameter(1, email); // query.setParameter(2, id); query.getResultList();
写表名,实体类名都不行。报错:
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - 对象名 'spatial_event' 无效。
或者
org.hibernate.QueryException: could not resolve property: point of: org.vaadin.example.SpatialEvent [select p from org.vaadin.example.SpatialEvent p where within(p.point, :circle) = true]
这是由于错写了这句:
spring.jpa.properties.hibernate.default_schema=dbo
1、先说说Sql Server中geometry和geography的区别:
geometry:planar 平面坐标系【supported by SQL Server conforms to the Open Geospatial Consortium (OGC) Simple Features for SQL Specification version 1.1.0.】
geography: terrestrial 地理坐标系【stores ellipsoidal (round-earth) data, such as GPS latitude and longitude coordinates.】
如果要计算两个lat/lon点之间的实际距离就需要将geometry类型转成geography类型,不然结果肯定不正确。
2、geometry转geography的方法:
geography::STGeomFromText(boundary.ToString(), 4326)
boundary是geometry类型的,4326是坐标系的参数,4326代表GCS-WGS-1984坐标系,是系统默认的坐标系。
可以通过这个sql获得系统的坐标系(Sql server中):Select * from sys.spatial_reference_systems where authorized_spatial_reference_id=4326
3、STDistance的用法:
https://msdn.microsoft.com/zh-cn/library/bb933952(v=sql.110).aspx
按照里面的例子能够计算出距离,但是如果输入的是经纬度的值,得出的结果总是觉得不对,值比较小,实际上需要按照第二步转化为geography类型再计算就可以了,4326坐标系默认返回距离的单位【unit】是米【meter】。
STDistance也可以计算点到面的最短距离。
---------------------
作者:Spring_Ji
来源:CSDN
原文:https://blog.csdn.net/jcx5083761/article/details/46010215?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!
----------------------------------------------------------------
参考:https://blog.csdn.net/bitree1/article/details/63253685