When it comes to open source spatial databases, PostGIS gets the lion’s share of attention, but MySQL has come a long way in its support of spatial features. Still, if you want to load spatial data from JDBC, the MySQL Connector/J JDBC libraries don’t provide Java classes for converting the data to spatial types, so you need to find another solution.
One approach is Geotools, which provides a datastore for loading features from MySQL. However, if you want something more lightweight, it’s fairly straightforward to load up a feature using the JTS WKBReader. That’s what I do for my Open Jump DB Query plugin.
Assuming your table is called “province”, and has a geometry column called “geom”, here’s how to query the database and load the resulting geometry:
// Do JDBC work to load driver, create connection, statement, etc. // Then.... String query = "SELECT geom FROM province" ; ResultSet resultSet = statement.executeQuery(query); while (resultSet.next()) { //MySQL geometries are returned in JDBC as binary streams. The //stream will be null if the record has no geometry. InputStream inputStream = resultSet.getBinaryStream( "geom" ); Geometry geometry = getGeometryFromInputStream(inputStream); // do something with geometry... } |
Here’s the code that does the actual InputStream to Geometry conversion:
private Geometry getGeometryFromInputStream(InputStream inputStream) throws Exception { Geometry dbGeometry = null ; if (inputStream != null ) { //convert the stream to a byte[] array //so it can be passed to the WKBReader byte [] buffer = new byte [ 255 ]; int bytesRead = 0 ; ByteArrayOutputStream baos = new ByteArrayOutputStream(); while ((bytesRead = inputStream.read(buffer)) != - 1 ) { baos.write(buffer, 0 , bytesRead); } byte [] geometryAsBytes = baos.toByteArray(); if (geometryAsBytes.length < 5 ) { throw new Exception( "Invalid geometry inputStream - less than five bytes" ); } //first four bytes of the geometry are the SRID, //followed by the actual WKB. Determine the SRID //here byte [] sridBytes = new byte [ 4 ]; System.arraycopy(geometryAsBytes, 0 , sridBytes, 0 , 4 ); boolean bigEndian = (geometryAsBytes[ 4 ] == 0x00 ); int srid = 0 ; if (bigEndian) { for ( int i = 0 ; i < sridBytes.length; i++) { srid = (srid << 8 ) + (sridBytes[i] & 0xff ); } } else { for ( int i = 0 ; i < sridBytes.length; i++) { srid += (sridBytes[i] & 0xff ) << ( 8 * i); } } //use the JTS WKBReader for WKB parsing WKBReader wkbReader = new WKBReader(); //copy the byte array, removing the first four //SRID bytes byte [] wkb = new byte [geometryAsBytes.length - 4 ]; System.arraycopy(geometryAsBytes, 4 , wkb, 0 , wkb.length); dbGeometry = wkbReader.read(wkb); dbGeometry.setSRID(srid); } return dbGeometry; } |
And that’s it. Pretty easy thanks to JTS!