2015-06-11 7 views
2

Я читаю набор данных, содержащих большое количество многополигонов. Я использую Geotools, и я хотел бы сохранить этот список в таблице базы данных mysql.Geotools MultiPolygon to DB и обратно

Я не знаю, как эффективно сохранять форму и иметь возможность воссоздать объект multipolygon.

Если я получу координаты мультиполя, тогда я получаю массив, содержащий значения всех вершин для этой геометрии (в случае, когда геометрия является составной, массив содержит все вершины для компонентов, в порядок, в котором компоненты встречаются в геометрии), но я не знаю, как воссоздать новый мультиполигон с этими координатами.

Подпишитесь ниже, что я получил.

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()); 
    } 
} 

В настоящее время из MultiPolygon я знаю, как получить полигон обратно (потому что я просто хранить координаты, и я использую их, чтобы создать полигон), но я не знаю, что делать, чтобы сохранить и извлечение мультиполигона. В целом, оптимальное решение будет работать для любой геометрии:

синтаксического анализа геометрии OBJ -> магазин геометрии к БД (с соответствующим ID) -> (спустя некоторое время ...) -> получить информацию о геометрии (по ID) -> построить новую геометрию 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, я хотел бы получить связанную информацию о фигуре(), а затем построить геометрию.

ответ

0

(не проверено) GeoTools имеет хранилище данных MySQL: http://docs.geotools.org/latest/javadocs/org/geotools/data/mysql/MySQLDataStoreFactory.html

также documetned здесь: http://docs.geotools.org/latest/userguide/library/jdbc/mysql.html

Вы должны быть в состоянии взять на себя FeatureCollection вы читали из SHP и подтолкнуть его к новому хранилищу данных. Таким образом,

SimpleFeatureCollection sfc 

является то, что вы хотите, чтобы перейти к источнику SimpleFeatureSource, который Вы определяете для этого хранилища.Что-то вроде

DataUtilities.source(collection); 

согласно руководству пользователя: http://docs.geotools.org/latest/userguide/library/main/collection.html

Надеется, что это помогает.

+0

Спасибо! Я изучаю это, но я, кажется, не нахожу то, что мне нужно. DataStore больше подходит для получения информации, а не для вставки информации в данную таблицу mysql. Я отредактирую вопрос, добавив более подробную информацию. – user1472709

1

Вы работаете на слишком низком уровне и, таким образом, усложняете себя. GeoTools разработан (для большинства пользователей/применений) для работы с DataStores, которые абстрагируют детали и функции, которые обрабатывают геометрию и атрибуты для вас. Таким образом, ваша проблема ломается в двух частях - сначала читается в шейп-файле, а вторая записывает функции в базу данных. Вы преуспели с первого шага, второй немного сложнее, но довольно легко.

Получить соединение с БД (я использовал 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, который создает новую таблицу, если это необходимо или добавляется к существующему.

+0

Спасибо, я! Мне не нравится способ настройки параметров в DataStores, и я не уверен, что код будет легче читать, если я хочу сохранить только некоторые конкретные атрибуты функций (мне, вероятно, придется отфильтровать атрибуты I не хотят хранить). Я просто разместил альтернативное решение, но я был бы рад услышать от вас, что вы думаете. – user1472709

+0

Вы можете использовать JNDI, если вы предпочитаете обрабатывать соединения таким образом. Самый простой способ выбрать только некоторые атрибуты - передать запрос в хранилище данных шейп-файла, которое ограничивает возвращаемые атрибуты, а также позволяет фильтровать возвращаемые функции. –

+1

Ответ Янта - это путь. Дополнительную подготовку (с хранилищем данных shp) смотрите здесь http://docs.geotools.org/stable/tutorials/feature/csv2shp.html Для управления атрибутами, которые необходимо сохранить в функции, вы управляете схемой (см. Ссылку как он создан). Если вы хотите подмножество, посмотрите на это: DataUtilties.createSubType (SimpleFeatureType, String []) здесь http://docs.geotools.org/stable/userguide/library/main/data.html – MartinT

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; 
    } 
} 

Это решение удовлетворяет меня, как и в таблице БД я могу видеть всю геометрию и сохранить остальную часть информации в таблице, которая уже создана в конкретном путь. Конечно, мне интересно услышать ваши комментарии.

+0

Это будет медленнее читать/write и предотвращает индексирование базы данных. Это также предотвратит использование стандартных инструментов сопоставления на вашем db. –

+1

Это решение в основном не использует Geotools. Он работает с JTS для геометрии. Это очень низкоуровневое решение, которое создавало бы проблемы в производственных реализациях, полагаясь на другие продвинутые Geotools. Вы также не манипулируете целыми функциями, просто геометрия (нетипизированная). Вы можете закончить смешивание линий и точек, полигонов и т. Д. В зависимости от бэкэнд это может быть или не быть возможным. – MartinT

+0

Как говорится выше, это решение может не использовать потенциал Geotools, и он может быть «низкоуровневым», поскольку он читает конкретный атрибут (то есть _the_geom_) каждой функции перед вставкой.Тем не менее, я протестировал это решение с файлом, содержащим более 3000 полигонов и мультиполигонов, и то, что у меня есть в файле формы, всегда соответствовало тому, что я получил из моей таблицы mysql после вставки. Обратите внимание, однако, что мне пришлось изменить тип столбца таблицы из текста в ** mediumtext **. – user1472709