- 引入依赖
<!--连接Postgresql数据库--> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> <!--编(解)码postgresql写入(或读取)的Geometry--> <dependency> <groupId>net.postgis</groupId> <artifactId>postgis-jdbc</artifactId> <version>2.5.0</version> </dependency> <!--Geometry工具库--> <dependency> <groupId>org.locationtech.jts</groupId> <artifactId>jts-core</artifactId> <version>1.17.0</version> </dependency>
- Entity编写
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonIgnore; import com.jd.risk.screen.demo.entity.handler.PointTypeHandler; import lombok.Data; import org.locationtech.jts.geom.Point; /** * 基站PO * * @author wangrubin * @date 2022-08-16 */ @Data @TableName(value = "t_base_station", autoResultMap = true) public class StationPO { /** * 基站ID */ @TableId(type = IdType.AUTO) private Long id; /** * 基站位置 */ @JsonIgnore @TableField(typeHandler = PointTypeHandler.class) private Point location; }
- 实现几何(Geometry)类型转换器
- 父类转换器逻辑
import lombok.SneakyThrows; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.io.WKTReader; import org.locationtech.jts.io.WKTWriter; import org.postgis.PGgeometry; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * Geometry字段和MyBatis类型转换器 * * @param <T> 具体的几何类型 * @author wangrubin * @date 2022-08-06 */ public abstract class AbstractGeometryTypeHandler<T extends Geometry> extends BaseTypeHandler<T> { /** * WKTReader非线程安全 */ private static final ThreadLocal<WKTReader> READER_POOL = ThreadLocal.withInitial(WKTReader::new); /** * WKTWriter非线程安全 */ private static final ThreadLocal<WKTWriter> WRITER_POOL = ThreadLocal.withInitial(WKTWriter::new); /** * 与数据库中几何列的空间坐标系保持一致,要不然写入会报错 */ private static final int SRID_IN_DB = 4326; @Override public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { PGgeometry pGgeometry = new PGgeometry(WRITER_POOL.get().write(parameter)); org.postgis.Geometry geometry = pGgeometry.getGeometry(); geometry.setSrid(SRID_IN_DB); ps.setObject(i, pGgeometry); } @SneakyThrows @Override public T getNullableResult(ResultSet rs, String columnName) { String string = rs.getString(columnName); return getResult(string); } @SneakyThrows @Override public T getNullableResult(ResultSet rs, int columnIndex) { String string = rs.getString(columnIndex); return getResult(string); } @SneakyThrows @Override public T getNullableResult(CallableStatement cs, int columnIndex) { String string = cs.getString(columnIndex); return getResult(string); } private T getResult(String string) throws SQLException { if(string == null){ return null; } PGgeometry pGgeometry = new PGgeometry(string); String s = pGgeometry.toString(); String target = String.format("SRID=%s;", SRID_IN_DB); String wkt = s.replace(target, ""); try { return (T) READER_POOL.get().read(wkt); } catch (Exception e) { throw new RuntimeException("解析wkt失败:" + wkt, e); } } }
- 子类转换器逻辑
import org.apache.ibatis.type.MappedTypes; import org.locationtech.jts.geom.Point; /** * Point的类型转换器 * * @author wangrubin1 * @date 2022-08-19 */ @MappedTypes({Point.class}) public class PointTypeHandler extends AbstractGeometryTypeHandler<Point> { }
- 建表语句
CREATE TABLE public.t_base_station ( id bigserial primary key, location geometry(Point,4326) -- 坐标系是4326 )
- 测试
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.jd.risk.screen.demo.entity.StationPO; import org.apache.ibatis.annotations.Mapper; @Mapper public interface StationMapper extends BaseMapper<StationPO> { }
@SpringBootTest(classes = DemoApplication.class) @ExtendWith(SpringExtension.class) @WebAppConfiguration class GeometryTests { @Autowired private StationMapper stationMapper; @Test public void insert() { GeometryFactory factory = new GeometryFactory(); StationPO stationPo = new StationPO(); stationPo.setLocation(factory.createPoint(new Coordinate(115.3, 24.7))); stationMapper.insert(stationPo); } @Test public void select() { StationPO stationPo = stationMapper.selectById(1L); System.out.println(stationPo); } }
控制台输出:StationPO(id=1, location=POINT (115.3 24.7))