geotools工具类中 DataStore(或者说SimpleFeature)如何写入SQLite数据库。
只需要geopkg这个依赖,里面包括了sqlite-jdbc。
<dependency> <groupId>org.geotools</groupId> <artifactId>gt-geopkg</artifactId> <version>${gt.version}</version> </dependency>
先获取DataStore,因为SQLite是基于文件实现,一个文件一个数据库,单写多读。
private DataStore getSqliteDataStore(String reqId) throws IOException { if (!Files.exists(Paths.get(cachePath))) { Files.createDirectory(Paths.get(cachePath)); } Map<String, String> params = new HashMap<>(); params.put("dbtype", "geopkg"); params.put("database", getCacheDb(reqId)); return DataStoreFinder.getDataStore(params); } private String getCacheDb(String reqId) { return cachePath + File.separator + reqId + ".db"; }
写入实现, 我们传入参数是一个SimpleFeature的迭代器,采用分批写入方式。
public void write(String reqId, SimpleFeatureIterator iterator) { if (!iterator.hasNext()) { return; } try { DataStore datastore = getSqliteDataStore(reqId); SimpleFeature f = iterator.next(); SimpleFeatureType featureType = f.getFeatureType(); final int batchSize = 512; List<SimpleFeature> batch = new ArrayList<>(batchSize); batch.add(f); // 建表 datastore.createSchema(featureType); SimpleFeatureSource source = datastore.getFeatureSource(featureType.getTypeName()); if (source instanceof SimpleFeatureStore) { SimpleFeatureStore store = (SimpleFeatureStore) source; while (iterator.hasNext()) { f = iterator.next(); batch.add(f); if (batch.size() == batchSize) { writeFeatures(featureType, batch, store); } } if (!batch.isEmpty()) { writeFeatures(featureType, batch, store); } } } catch (IOException e) { log.error("Write Error", e); } }
分批写入:
private void writeFeatures(SimpleFeatureType featureType, List<SimpleFeature> batch, SimpleFeatureStore store) throws IOException { Transaction transaction = new DefaultTransaction("create"); try { store.addFeatures(new ListFeatureCollection(featureType, batch)); transaction.commit(); batch.clear(); } catch (Exception e) { log.warn("Write SimpleFeature Error", e); transaction.rollback(); } finally { transaction.close(); } }
读取采用直接用JDBC读SQLite数据库,返回分页数据。ResultSetFeatureIterator
在这里自己实现,就是ResultSet
转SimpleFeatureIterator
,并不重要。
public PageResultData read(String reqId, int current, int pageSize) { try (Connection connection = DriverManager.getConnection("jdbc:sqlite:" + getCacheDb(reqId))) { Statement statement = connection.createStatement(); statement.setQueryTimeout(30); // set timeout to 30 sec. ResultSet rs = statement.executeQuery(String.format("select count(1) from %s", reqId)); rs.next(); int total = rs.getInt(1); rs = statement.executeQuery(String.format("select * from %s limit %s offset %s", reqId, pageSize, current - 1)); ResultSetFeatureIterator it = new ResultSetFeatureIterator(reqId, rs); List<SimpleFeature> features = new ArrayList<>(pageSize); while (it.hasNext()) { features.add(it.next()); } return new PageResultData(features, current, pageSize, total); } catch (SQLException e) { log.error("Get Page Sqlite Error", e); } return new PageResultData(); }
@Test public void testSqliteAccessFeature() { String reqId = "req" + System.currentTimeMillis(); // 写,构造数据 SimpleFeatureTypeBuilder bt = new SimpleFeatureTypeBuilder(); bt.add("name", String.class); bt.setName(reqId); SimpleFeatureType sft = bt.buildFeatureType(); ListFeatureCollection simpleFeatures = new ListFeatureCollection(sft, new SimpleFeature[]{ SimpleFeatureBuilder.build(sft, new Object[]{"jimo"}, null), SimpleFeatureBuilder.build(sft, new Object[]{"hehe"}, null), SimpleFeatureBuilder.build(sft, new Object[]{"lily"}, null) }); // 调用 write(reqId, new DelegateSimpleFeatureIterator(simpleFeatures.iterator())); // 分页读 PageResultData data = read(reqId, 1, 10); assertEquals(3, data.getTotal()); assertEquals(3, data.getFeatures().size()); }