Geotools MultiPolygon到DB和返回

时间:2015-06-11 13:54:29

标签: java mysql jdbc geotools

我正在阅读一组包含大量多种多样性的数据。我正在使用Geotools,我想将此列表存储在mysql数据库表中。

我不知道如何以有效的方式存储形状,并且能够重新创建多面体对象。

如果我得到多边形的坐标,那么我得到一个数组,其中包含此几何体的所有顶点的值(如果几何体是复合体,则数组包含组件的所有顶点,顺序其中组件出现在几何体中),但我不知道如何使用这些坐标重新创建一个新的多边形。

请在下面找到我所得到的内容。

private List<Shape> parseFile2ShapeList(File file) {

    List<Shape> shapes = new ArrayList<Shape>();
    FileDataStore myData = null;
    SimpleFeatureIterator sfit = null;
    try {
        // Extract all features
        myData = FileDataStoreFinder.getDataStore( file );
        SimpleFeatureSource source = myData.getFeatureSource();
        SimpleFeatureCollection sfc = source.getFeatures();
        sfit = sfc.features();

        // Read the features and store in a list only the ones with Venue_ID
        while (sfit.hasNext()) {
            SimpleFeature feature = sfit.next();
            String id = (String) feature.getAttribute("ID");
            MultiPolygon mulPoly = (MultiPolygon) feature.getAttribute("the_geom");
            Shape shape = new Shape(id, mulPoly);
            shapes.add(shape);
        }  
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        sfit.close();
        myData.dispose();
    }
    return shapes;
}

private boolean insertShapes(List<Shape> shapes) {
    // Insert the shapes in the DB
    boolean inserted = false;
    try (Database db = new Database()) {
        // Store in the DB all the shapes
        for (Shape shape : shapes) {
            db.getShapesDao().insertShape(shape); // What shall I store in the DB if the shape is a multipolygon? What if it is any Geometry?
        }   
        inserted = true;
    } catch (SQLException e) {
        e.printStackTrace();
        inserted = false;
    } catch (IOException e) {
        e.printStackTrace();
        inserted = false;
    }
    return inserted;
}

private Shape selectShape(String shape_id) {
    Shape shape = null;
    try (Database db = new Database()) {
        // Retrieve the shape
        shape = db.getShapesDao().getShapeById(shape_id); // How do I recreate a multipolygon (or any other Geometry inserted in the DB?)
    } catch (SQLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return shape;
}

public void main() {

    // display a data store file chooser dialog for shapefiles
    File file = JFileDataStoreChooser.showOpenFile("shp", null);
    if (file == null) {
        return;
    }

    // Read the file and load in memory the venues
    List<Shape> shapes = parseFile2ShapeList(file);
    System.out.println("Shapes parsed: " + retrieved.size());
    for (Shape shape : shapes) {
        System.out.println("\t ID: " + shape.getId() ); 
    }

    // Insert in database
    boolean inserted = insertVenues(venues);
    System.out.println("Insertion successful? " + inserted);

    // Retrieve from database
    List<Shape> retrievedShapes = new ArrayList<Shape>();
    for (Shape shape : shapes) {
        Shape retrieved = selectShape(shape.getId());
        retrievedShapes.add(retrieved);
    }
    System.out.println("Shapes retrieved: " + retrieved.size());
    for (Shape shape : retrievedShapes) {
        System.out.println("\t ID: " + shape.getId() ); 
    }
}

目前,从多边形我知道如何获得多边形(因为我只是存储坐标,我用它们来创建一个多边形),但我不知道如何存储和检索多边形。 通常,最佳解决方案适用于任何几何:

  

解析几何obj - &gt;将几何存储到DB(具有关联的ID) - &gt; (一段时间后......) - &gt;检索几何信息(通过ID) - &gt;构造新的几何体obj

新对象将是原始对象的副本,不再可用。

PS:序列化一个Java对象并将其存储在数据库中是我不想做的事情,因为我希望在数据库中有某种人类可读的东西。 :)

----编辑

我在收到答案后添加了更多信息(谢谢@ user2731872!)。

我想存储的数据库表具有以下模式:

mysql> describe shape_table;
+-----------------+----------------------+------+-----+---------+----------------+
| Field           | Type                 | Null | Key | Default | Extra          |
+-----------------+----------------------+------+-----+---------+----------------+
| id              | int(10) unsigned     | NO   | PRI | NULL    | auto_increment |
| shape_id        | varchar(32)          | NO   |     | NULL    |                |
| shape           | text                 | NO   |     | NULL    |                |
+-----------------+----------------------+------+-----+---------+----------------+

此表还有其他列,但目前它们并不相关。在任何情况下,给定输入文件,我想将每个几何(shape列)存储在不同的行中。

在我的程序中,给定shape_id我想检索有关形状(shape列)的相关信息,然后构建几何体。

3 个答案:

答案 0 :(得分:1)

你的工作水平太低,因此对自己造成了很大的困难。 GeoTools设计(适用于大多数用户/用户)使用DataStore来抽象细节,以及为您处理几何和属性的功能。因此,您的问题分为两部分 - 第一次读取shapefile,第二次将功能写入数据库。你已经成功完成了第一步,第二步有点棘手,但相当容易。

获取与数据库的连接(我已经安装了PostGIS,但是MySql应该以相同的方式工作):

params.put("user", "geotools");
params.put("passwd", "geotools");
params.put("port", "5432");
params.put("host", "127.0.0.1");
params.put("database", "geotools");
params.put("dbtype", "postgis");
dataStore = DataStoreFinder.getDataStore(params);

然后将功能发送到dataSource:

SimpleFeatureSource featureSource = dataStore
.getFeatureSource(schema.getName().getLocalPart());
if (featureSource instanceof SimpleFeatureStore) {
    SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
    featureStore.setTransaction(transaction);
    try {
        List < FeatureId > ids = featureStore.addFeatures(features);
        transaction.commit();
    } catch (Exception problem) {
        problem.printStackTrace();
        transaction.rollback();
    } finally {
        transaction.close();
    }
    dataStore.dispose();
    return true;
} else {
    dataStore.dispose();
    System.err.println("Database not writable");
    return false;
}

如果需要,可以在新表的句柄创建方面有些混乱,例如您可以在full code中看到的,如果需要,可以创建新表或附加到现有表。

答案 1 :(得分:0)

(未经测试)Geotools有一个MySQL数据存储: http://docs.geotools.org/latest/javadocs/org/geotools/data/mysql/MySQLDataStoreFactory.html

此处还有文件:http://docs.geotools.org/latest/userguide/library/jdbc/mysql.html

您应该能够从SHP读取FeatureCollection并将其推送到新的数据存储区。因此,

SimpleFeatureCollection sfc 

是您要传递给为此数据存储定义的SimpleFeatureSource源的内容。像

这样的东西
DataUtilities.source( collection );

根据用户指南:http://docs.geotools.org/latest/userguide/library/main/collection.html

希望这有帮助。

答案 2 :(得分:0)

我找到的解决方案是使用WKTWriter和WKTReader类。这是我在DAO课程中写的:

static private String INSERT_SHAPE = "INSERT INTO shape_table(shape_id, shape) VALUES (?, ?)";

static private String GET_SHAPE_BY_ID = "SELECT shape FROM shape_table WHERE shape_id = ?";


public void insertShape(String shape_id, Geometry shape) throws SQLException {
    try (PreparedStatement s = connection.prepareStatement(INSERT_SHAPE)) {
        s.setString(1, shape_id);
        WKTWriter writer = new WKTWriter();
        String wkt = writer.write(shape);
        s.setString(2, wkt);
        s.executeUpdate();
    }
}

public Geometry getShapeById(String shape_id) throws SQLException, ParseException {
    String wkt = null;
    Geometry shape = null;
    WKTReader reader = new WKTReader();
    try (PreparedStatement s = connection.prepareStatement(GET_SHAPE_BY_ID)) {
        s.setString(1, shape_id);
        ResultSet rs = s.executeQuery();
        if (rs.next()) {
            wkt = rs.getString("shape");
            shape = reader.read(wkt);
        }
        return shape;
    }
}

这个解决方案让我满意,就像在DB表中我可以看到整个几何体并将其余信息存储在已经以特定方式创建的表中。我当然有兴趣听取你的意见。