zhongrj
2023-11-28 2f5f60384a5f469787edbe333aaa265fae58bf2d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package org.springblade.modules.grid.handle;
 
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.io.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
 
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
@MappedTypes({String.class})
@MappedJdbcTypes({JdbcType.OTHER})
@Slf4j
public class GeometryTypeHandler extends BaseTypeHandler<String> {
 
 
    /**
     * 设置转换
     * @param preparedStatement
     * @param i
     * @param s
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, String s, JdbcType jdbcType) throws SQLException {
        try{
            //String转Geometry
            Geometry geo = new WKTReader(new GeometryFactory(new PrecisionModel())).read(s);
            // Geometry转WKB
            byte[] geometryBytes = new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN, false).write(geo);
            // 设置SRID为mysql默认的 0
            byte[] wkb = new byte[geometryBytes.length+4];
            wkb[0] = wkb[1] = wkb[2] = wkb[3] = 0;
            System.arraycopy(geometryBytes, 0, wkb, 4, geometryBytes.length);
            preparedStatement.setBytes(i,wkb);
        }catch (ParseException e){
            log.error("坐标转换异常:【{}】",e.getMessage(),e);
        }
    }
 
    @Override
    public String getNullableResult(ResultSet resultSet, String s){
        try(
            InputStream inputStream = resultSet.getBinaryStream(s)){
            Geometry geo = getGeometryFromInputStream(inputStream);
            if(geo != null){
                return geo.toString();
            }
        }catch(Exception e){
            log.error("坐标转换异常:【{}】",e.getMessage(),e);
        }
        return null;
    }
 
    @Override
    public String getNullableResult(ResultSet resultSet, int i){
        try(InputStream inputStream = resultSet.getBinaryStream(i)){
            Geometry geo = getGeometryFromInputStream(inputStream);
            if(geo != null){
                return geo.toString();
            }
        }catch(Exception e){
            log.error("坐标转换异常:【{}】",e.getMessage(),e);
        }
        return null;
    }
 
    @Override
    public String getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        System.out.println("i = " + i);
        return "";
    }
 
    /**
     * 流 转 geometry
     * */
    private  Geometry getGeometryFromInputStream(InputStream inputStream) throws Exception {
 
        Geometry dbGeometry = null;
 
        if (inputStream != null) {
            // 二进制流转成字节数组
            byte[] buffer = new byte[255];
 
            int bytesRead;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }
            // 得到字节数组
            byte[] geometryAsBytes = baos.toByteArray();
            // 字节数组小于5 异常
            if (geometryAsBytes.length < 5) {
                throw new RuntimeException("坐标异常");
            }
 
            //字节数组前4个字节表示srid 去掉
            byte[] sridBytes = new byte[4];
            System.arraycopy(geometryAsBytes, 0, sridBytes, 0, 4);
            boolean bigEndian = (geometryAsBytes[4] == 0x00);
            // 解析srid
            int srid = 0;
            if (bigEndian) {
                for (byte sridByte : sridBytes) {
                    srid = (srid << 8) + (sridByte & 0xff);
                }
            } else {
                for (int i = 0; i < sridBytes.length; i++) {
                    srid += (sridBytes[i] & 0xff) << (8 * i);
                }
            }
 
            WKBReader wkbReader = new WKBReader();
            // WKBReader 把字节数组转成geometry对象。
            byte[] wkb = new byte[geometryAsBytes.length - 4];
            System.arraycopy(geometryAsBytes, 4, wkb, 0, wkb.length);
            dbGeometry = wkbReader.read(wkb);
            dbGeometry.setSRID(srid);
        }
        return dbGeometry;
    }
}