1. Modélisation géométrique dans MySQL
Pour gérer efficacement des données localisées, MySQL propose des types géométriques natifs tels que POINT, POLYGON ou LINESTRING. Une table typique pourrait être définie ainsi :
CREATE TABLE location_map (
id INT PRIMARY KEY AUTO_INCREMENT,
anchor POINT NOT NULL SRID 4326,
boundary POLYGON NOT NULL SRID 4326,
INDEX idx_anchor (anchor) USING SPATIAL,
INDEX idx_boundary (boundary) USING SPATIAL
);
Remarque importante : les index spatiaux exigent que les colonnes soient déclarées NOT NULL et qu’un SRID (système de référence spatiale) soit explicitement spécifié — ici SRID 4326 pour WGS84.
2. Requêtes géospatiales courantes
Les fonctions ST_Within et ST_Intersects permettent de tester des relations topologiques entre géométries. Exemples concrets :
- Vérifier si un point donné est à l’intérieur d’un polygone :
SELECT id FROM location_map
WHERE ST_Within(
ST_GeomFromText('POINT(12.345 45.678)', 4326),
boundary
);
- Détecter l’intersection entre deux polygones (par exemple, zones administratives chevauchantes) :
SELECT a.id AS zone_a, b.id AS zone_b
FROM location_map a, location_map b
WHERE a.id < b.id
AND ST_Intersects(a.boundary, b.boundary);
Attention : les polygones doivent être fermés — la première et dernière coordonnée doivent coïncider, sinon ST_GeomFromText() échouera ou produira un comportement imprévisible.
3. Intégration côté Java avec JTS et MyBatis
Pour manipuler des géométries en Java, la bibliothèque JTS Topology Suite (v1.19+) est recommandée. Elle remplace avantageusement la version obsolète com.vividsolutions:jts.
Voici un gestionnaire de type personnalisé compatible avec MyBatis :
@MappedTypes({Point.class})
@Component
public class PointTypeHandler extends BaseTypeHandler<Point> {
private final GeometryFactory factory = new GeometryFactory(new PrecisionModel(), 4326);
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Point point, JdbcType jdbcType)
throws SQLException {
if (point == null) {
ps.setNull(i, Types.BINARY);
return;
}
WKBWriter writer = new WKBWriter(2, true);
byte[] wkb = writer.write(point);
ps.setBytes(i, wkb);
}
@Override
public Point getNullableResult(ResultSet rs, String columnName) throws SQLException {
byte[] data = rs.getBytes(columnName);
return parseWKB(data);
}
private Point parseWKB(byte[] bytes) {
if (bytes == null) return null;
try {
WKBReader reader = new WKBReader(factory);
return (Point) reader.read(bytes);
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid WKB geometry", e);
}
}
}
4. Calculs géométriques précis avec GeoTools
Pour obtenir des mesures réelles (surface en m², longueur en mètres), il faut reprojeter les géométries depuis le système géodésique (WGS84) vers un système projeté comme EPSG:3857 ou EPSG:3395. Voici une implémentation robuste utilisant GeoTools 28+ :
public double computeAreaInSquareMeters(Geometry geom) {
if (geom == null || geom.isEmpty()) return 0.0;
try {
CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326");
CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3395"); // Mercator sphérique
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
Geometry projected = JTS.transform(geom, transform);
return projected.getArea();
} catch (Exception e) {
throw new IllegalStateException("Failed to project geometry for area calculation", e);
}
}
Cette approche garantit une précision métrique acceptable pour la plupart des applications cartographiques — contrairement à EPSG:3857, qui distord les surfaces aux hautes latitudes.
5. Dépendances Maven recommandées
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.19.0</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>28.4</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-referencing</artifactId>
<version>28.4</version>
</dependency>
Aucune configuration de dépôt supplémentaire n’est requise : GeoTools 28+ est publié sur Maven Central.