代码提交

This commit is contained in:
2025-10-09 11:03:15 +08:00
parent 65048fbe89
commit 3e9cac5e32
22 changed files with 1195 additions and 269 deletions

View File

@ -34,7 +34,7 @@ public class CodeUtil {
}
// 传入需要生成代码的表名
Generation("web_source");
Generation("pbf_info");
}
public static void Generation(String... tableName) {

View File

@ -0,0 +1,470 @@
package com.yj.earth.common.util;
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import org.gdal.osr.CoordinateTransformation;
import org.gdal.osr.SpatialReference;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.gdal.ogr.ogrConstants.*;
/**
* GDAL地理数据转JSON工具类
*/
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import org.gdal.osr.SpatialReference;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* GDAL地理数据转JSON工具类
*/
public class GdalJsonConverter {
static {
// 初始化GDAL
gdal.AllRegister();
}
/**
* 将地理数据文件转换为指定结构的JSON
* @param filePath 文件绝对路径
* @return JSON字符串
*/
public static String convertToJson(String filePath) {
return convertToJson(filePath, "");
}
/**
* 将地理数据文件转换为指定结构的JSON
* @param filePath 文件绝对路径
* @param targetCrs 目标坐标系(如:"EPSG:4326"),为空则不转换
* @return JSON字符串
*/
public static String convertToJson(String filePath, String targetCrs) {
try {
// 打开数据源
DataSource dataSource = ogr.Open(filePath, 0);
if (dataSource == null) {
throw new RuntimeException("无法打开文件: " + filePath);
}
JSONObject result = new JSONObject();
JSONArray listArray = new JSONArray();
// 获取所有图层
int layerCount = dataSource.GetLayerCount();
for (int i = 0; i < layerCount; i++) {
Layer layer = dataSource.GetLayer(i);
String layerName = layer.GetName();
JSONObject featureCollection = createFeatureCollection(layer, layerName, targetCrs);
if (featureCollection != null) {
listArray.put(featureCollection);
}
}
result.put("list", listArray);
dataSource.delete();
return result.toString(2); // 缩进2个空格美化输出
} catch (Exception e) {
throw new RuntimeException("转换失败: " + e.getMessage(), e);
}
}
/**
* 创建FeatureCollection对象
*/
private static JSONObject createFeatureCollection(Layer layer, String layerName, String targetCrs) throws JSONException {
JSONObject featureCollection = new JSONObject();
featureCollection.put("type", "FeatureCollection");
featureCollection.put("name", layerName);
// 获取源坐标系
String crsSrc = getLayerCrs(layer);
featureCollection.put("crs_src", crsSrc != null ? crsSrc : "");
// 设置目标坐标系
featureCollection.put("crs_dst", targetCrs != null ? targetCrs : "");
JSONArray featuresArray = new JSONArray();
Feature feature;
// 重置图层读取位置
layer.ResetReading();
// 获取图层定义,用于字段信息
FeatureDefn layerDefn = layer.GetLayerDefn();
// 如果需要坐标转换,创建坐标转换对象
SpatialReference sourceSrs = layer.GetSpatialRef();
SpatialReference targetSrs = null;
CoordinateTransformation coordTrans = null;
if (targetCrs != null && !targetCrs.isEmpty() && sourceSrs != null) {
try {
targetSrs = new SpatialReference();
if (targetCrs.startsWith("EPSG:")) {
int epsgCode = Integer.parseInt(targetCrs.substring(5));
targetSrs.ImportFromEPSG(epsgCode);
} else {
targetSrs.ImportFromProj4(targetCrs);
}
coordTrans = new CoordinateTransformation(sourceSrs, targetSrs);
} catch (Exception e) {
System.err.println("坐标转换初始化失败: " + e.getMessage());
}
}
while ((feature = layer.GetNextFeature()) != null) {
JSONObject featureObj = createFeature(feature, layerDefn, coordTrans, targetSrs != null);
if (featureObj != null) {
featuresArray.put(featureObj);
}
feature.delete();
}
// 清理资源
if (coordTrans != null) {
coordTrans.delete();
}
if (targetSrs != null) {
targetSrs.delete();
}
featureCollection.put("features", featuresArray);
return featureCollection;
}
/**
* 获取图层的坐标系信息
*/
private static String getLayerCrs(Layer layer) {
try {
SpatialReference srs = layer.GetSpatialRef();
if (srs != null) {
// 优先尝试获取PROJ4字符串
String proj4 = srs.ExportToProj4();
if (proj4 != null && !proj4.trim().isEmpty()) {
return proj4.trim();
}
// 如果PROJ4为空尝试获取WKT
String wkt = srs.ExportToWkt();
if (wkt != null && !wkt.trim().isEmpty()) {
return wkt.trim();
}
// 最后尝试获取EPSG代码
String authorityCode = srs.GetAuthorityCode(null);
String authorityName = srs.GetAuthorityName(null);
if (authorityName != null && authorityCode != null) {
return authorityName + ":" + authorityCode;
}
}
} catch (Exception e) {
System.err.println("获取坐标系信息失败: " + e.getMessage());
}
return null;
}
/**
* 创建单个Feature对象
*/
private static JSONObject createFeature(Feature feature, FeatureDefn layerDefn,
CoordinateTransformation coordTrans, boolean transformCoords) throws JSONException {
JSONObject featureObj = new JSONObject();
featureObj.put("type", "Feature");
// 处理属性字段
JSONObject properties = new JSONObject();
int fieldCount = layerDefn.GetFieldCount();
for (int i = 0; i < fieldCount; i++) {
FieldDefn fieldDefn = layerDefn.GetFieldDefn(i);
String fieldName = fieldDefn.GetName();
Object fieldValue = getFieldValue(feature, fieldDefn, i);
if (fieldValue != null) {
properties.put(fieldName, fieldValue);
}
}
featureObj.put("properties", properties);
// 处理几何图形
Geometry geometry = feature.GetGeometryRef();
if (geometry != null && !geometry.IsEmpty()) {
Geometry geomToUse = geometry;
// 如果需要坐标转换
if (transformCoords && coordTrans != null) {
try {
Geometry transformedGeom = geometry.Clone();
transformedGeom.Transform(coordTrans);
geomToUse = transformedGeom;
} catch (Exception e) {
System.err.println("坐标转换失败: " + e.getMessage());
// 如果转换失败,使用原始几何
geomToUse = geometry;
}
}
JSONObject geometryObj = convertGeometryToJson(geomToUse);
featureObj.put("geometry", geometryObj);
// 清理临时几何对象
if (geomToUse != geometry) {
geomToUse.delete();
}
} else {
// 如果没有几何信息创建空的MultiPolygon
featureObj.put("geometry", createEmptyMultiPolygon());
}
return featureObj;
}
/**
* 获取字段值
*/
private static Object getFieldValue(Feature feature, FieldDefn fieldDefn, int fieldIndex) {
int fieldType = fieldDefn.GetFieldType();
if (feature.IsFieldSet(fieldIndex)) {
switch (fieldType) {
case ogr.OFTInteger:
return feature.GetFieldAsInteger(fieldIndex);
case ogr.OFTInteger64:
return feature.GetFieldAsInteger64(fieldIndex);
case ogr.OFTReal:
return feature.GetFieldAsDouble(fieldIndex);
case ogr.OFTString:
return feature.GetFieldAsString(fieldIndex);
case ogr.OFTDate:
case ogr.OFTTime:
case ogr.OFTDateTime:
return feature.GetFieldAsString(fieldIndex);
default:
return feature.GetFieldAsString(fieldIndex);
}
}
return null;
}
/**
* 将几何图形转换为JSON
*/
private static JSONObject convertGeometryToJson(Geometry geometry) throws JSONException {
JSONObject geometryObj = new JSONObject();
String geometryType = geometry.GetGeometryName();
// 根据几何类型处理
switch (geometry.GetGeometryType()) {
case wkbPoint:
case wkbPoint25D:
geometryObj.put("type", "Point");
geometryObj.put("coordinates", getPointCoordinates(geometry));
break;
case wkbLineString:
case wkbLineString25D:
geometryObj.put("type", "LineString");
geometryObj.put("coordinates", getLineStringCoordinates(geometry));
break;
case wkbPolygon:
case wkbPolygon25D:
geometryObj.put("type", "Polygon");
geometryObj.put("coordinates", getPolygonCoordinates(geometry));
break;
case wkbMultiPoint:
case wkbMultiPoint25D:
geometryObj.put("type", "MultiPoint");
geometryObj.put("coordinates", getMultiPointCoordinates(geometry));
break;
case wkbMultiLineString:
case wkbMultiLineString25D:
geometryObj.put("type", "MultiLineString");
geometryObj.put("coordinates", getMultiLineStringCoordinates(geometry));
break;
case wkbMultiPolygon:
case wkbMultiPolygon25D:
geometryObj.put("type", "MultiPolygon");
geometryObj.put("coordinates", getMultiPolygonCoordinates(geometry));
break;
case wkbGeometryCollection:
case wkbGeometryCollection25D:
geometryObj.put("type", "GeometryCollection");
geometryObj.put("geometries", getGeometryCollection(geometry));
break;
default:
// 默认使用WKT格式
geometryObj.put("type", geometryType);
geometryObj.put("wkt", geometry.ExportToWkt());
break;
}
return geometryObj;
}
/**
* 获取点坐标
*/
private static JSONArray getPointCoordinates(Geometry geometry) throws JSONException {
JSONArray coords = new JSONArray();
coords.put(geometry.GetX());
coords.put(geometry.GetY());
if (geometry.GetGeometryType() == wkbPoint25D) {
coords.put(geometry.GetZ());
}
return coords;
}
/**
* 获取线坐标
*/
private static JSONArray getLineStringCoordinates(Geometry geometry) throws JSONException {
JSONArray coords = new JSONArray();
int pointCount = geometry.GetPointCount();
for (int i = 0; i < pointCount; i++) {
JSONArray point = new JSONArray();
point.put(geometry.GetX(i));
point.put(geometry.GetY(i));
if (geometry.GetGeometryType() == wkbLineString25D) {
point.put(geometry.GetZ(i));
}
coords.put(point);
}
return coords;
}
/**
* 获取多边形坐标
*/
private static JSONArray getPolygonCoordinates(Geometry geometry) throws JSONException {
JSONArray rings = new JSONArray();
// 外环
Geometry exteriorRing = geometry.GetGeometryRef(0);
rings.put(getLineStringCoordinates(exteriorRing));
// 内环(如果有)
int ringCount = geometry.GetGeometryCount();
for (int i = 1; i < ringCount; i++) {
Geometry interiorRing = geometry.GetGeometryRef(i);
rings.put(getLineStringCoordinates(interiorRing));
}
return rings;
}
/**
* 获取多点坐标
*/
private static JSONArray getMultiPointCoordinates(Geometry geometry) throws JSONException {
JSONArray points = new JSONArray();
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry point = geometry.GetGeometryRef(i);
points.put(getPointCoordinates(point));
}
return points;
}
/**
* 获取多线坐标
*/
private static JSONArray getMultiLineStringCoordinates(Geometry geometry) throws JSONException {
JSONArray lines = new JSONArray();
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry line = geometry.GetGeometryRef(i);
lines.put(getLineStringCoordinates(line));
}
return lines;
}
/**
* 获取多多边形坐标
*/
private static JSONArray getMultiPolygonCoordinates(Geometry geometry) throws JSONException {
JSONArray polygons = new JSONArray();
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry polygon = geometry.GetGeometryRef(i);
polygons.put(getPolygonCoordinates(polygon));
}
return polygons;
}
/**
* 获取几何集合
*/
private static JSONArray getGeometryCollection(Geometry geometry) throws JSONException {
JSONArray geometries = new JSONArray();
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry geom = geometry.GetGeometryRef(i);
geometries.put(convertGeometryToJson(geom));
}
return geometries;
}
/**
* 创建空的MultiPolygon几何
*/
private static JSONObject createEmptyMultiPolygon() throws JSONException {
JSONObject geometry = new JSONObject();
geometry.put("type", "MultiPolygon");
geometry.put("coordinates", new JSONArray());
return geometry;
}
/**
* 获取文件信息(辅助方法)
*/
public static Map<String, Object> getFileInfo(String filePath) {
Map<String, Object> info = new HashMap<>();
try {
DataSource dataSource = ogr.Open(filePath, 0);
if (dataSource != null) {
info.put("driver", dataSource.GetDriver().GetName());
info.put("layerCount", dataSource.GetLayerCount());
List<Map<String, Object>> layers = new ArrayList<>();
for (int i = 0; i < dataSource.GetLayerCount(); i++) {
Layer layer = dataSource.GetLayer(i);
Map<String, Object> layerInfo = new HashMap<>();
layerInfo.put("name", layer.GetName());
layerInfo.put("featureCount", layer.GetFeatureCount());
layerInfo.put("geometryType", ogr.GeometryTypeToName(layer.GetGeomType()));
// 添加坐标系信息
String crs = getLayerCrs(layer);
layerInfo.put("crs", crs != null ? crs : "未知");
layers.add(layerInfo);
}
info.put("layers", layers);
dataSource.delete();
}
} catch (Exception e) {
info.put("error", e.getMessage());
}
return info;
}
}

View File

@ -1,247 +0,0 @@
package com.yj.earth.common.util;
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GdalUtil {
// 静态初始化ObjectMapper避免重复创建
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
// 静态初始化GDAL
static {
// 可以考虑设置缓存目录来提升性能
gdal.SetConfigOption("GDAL_CACHEMAX", "1024"); // 设置1GB缓存
gdal.SetConfigOption("PROJ_LIB", "./lib");
gdal.AllRegister();
}
/**
* 读取矢量文件、将每个图层转换为符合指定格式的 GeoJSON
*/
public static String readVectorToSpecifiedGeoJson(String filePath) {
DataSource dataSource = null;
try {
// 打开矢量文件,使用只读模式
dataSource = ogr.Open(filePath, 0);
if (dataSource == null) {
throw new RuntimeException("无法打开矢量文件: " + filePath + ", 错误信息: " + gdal.GetLastErrorMsg());
}
// 创建结果结构,预先估计容量
Map<String, Object> result = new HashMap<>(2);
int layerCount = dataSource.GetLayerCount();
List<Map<String, Object>> layerList = new ArrayList<>(layerCount);
// 处理每个图层
for (int i = 0; i < layerCount; i++) {
Layer layer = dataSource.GetLayer(i);
if (layer == null) continue;
// 为当前图层创建符合格式的 GeoJSON
Map<String, Object> layerGeoJson = convertLayerToSpecifiedFormat(layer);
if (layerGeoJson != null) {
layerList.add(layerGeoJson);
}
// 提前释放图层资源
layer.delete();
}
result.put("list", layerList);
// 使用单例ObjectMapper转换为JSON字符串
return OBJECT_MAPPER.writeValueAsString(result);
} catch (Exception e) {
throw new RuntimeException("处理矢量文件时发生错误: " + e.getMessage() + ", 详细错误: " + gdal.GetLastErrorMsg(), e);
} finally {
// 确保数据源被正确释放
if (dataSource != null) {
dataSource.delete();
}
}
}
/**
* 将单个图层转换为符合指定格式的 GeoJSON
*/
private static Map<String, Object> convertLayerToSpecifiedFormat(Layer layer) {
try {
// 获取要素数量,预分配集合大小
long featureCount = layer.GetFeatureCount();
if (featureCount <= 0) {
return null; // 跳过空图层
}
// 创建符合格式的 GeoJSON FeatureCollection
Map<String, Object> geoJson = new HashMap<>(3);
geoJson.put("type", "FeatureCollection");
geoJson.put("name", layer.GetName());
// 预分配要素列表容量
List<Map<String, Object>> features = new ArrayList<>((int) Math.min(featureCount, Integer.MAX_VALUE));
// 获取字段定义
FeatureDefn featureDefn = layer.GetLayerDefn();
int fieldCount = featureDefn.GetFieldCount();
// 缓存字段信息,避免重复获取
String[] fieldNames = new String[fieldCount];
int[] fieldTypes = new int[fieldCount];
for (int j = 0; j < fieldCount; j++) {
FieldDefn fieldDef = featureDefn.GetFieldDefn(j);
fieldNames[j] = fieldDef.GetName();
fieldTypes[j] = fieldDef.GetFieldType();
}
// 读取图层中的所有要素
layer.ResetReading();
Feature feature;
while ((feature = layer.GetNextFeature()) != null) {
Map<String, Object> featureMap = new HashMap<>(3);
featureMap.put("type", "Feature");
// 处理属性
Map<String, Object> properties = new HashMap<>(fieldCount);
for (int j = 0; j < fieldCount; j++) {
properties.put(fieldNames[j], getFieldValue(feature, j, fieldTypes[j]));
}
featureMap.put("properties", properties);
// 处理几何信息 - 直接构建Map而不是先转JSON再解析
Geometry geometry = feature.GetGeometryRef();
featureMap.put("geometry", convertGeometryToMap(geometry));
features.add(featureMap);
feature.delete(); // 及时释放要素资源
}
geoJson.put("features", features);
return geoJson;
} catch (Exception e) {
System.err.println("转换图层 " + layer.GetName() + " 时发生错误: " + e.getMessage() + ", 详细错误: " + gdal.GetLastErrorMsg());
return null;
}
}
/**
* 将Geometry直接转换为Map避免JSON序列化/反序列化开销
*/
private static Map<String, Object> convertGeometryToMap(Geometry geometry) {
if (geometry == null) {
return createEmptyMultiPolygon();
}
try {
String geometryType = geometry.GetGeometryName();
Map<String, Object> geometryMap = new HashMap<>(2);
// 如果不是MultiPolygon尝试转换
if (!"MULTIPOLYGON".equals(geometryType)) {
// 转换为MultiPolygon
Geometry multiPolygon = geometry.MakeValid();
if (!"MULTIPOLYGON".equals(multiPolygon.GetGeometryName())) {
multiPolygon = geometry.Buffer(0); // 修复几何问题
}
if (!"MULTIPOLYGON".equals(multiPolygon.GetGeometryName())) {
// 如果仍然不是MultiPolygon创建空的
return createEmptyMultiPolygon();
}
geometry = multiPolygon;
}
geometryMap.put("type", "MultiPolygon");
geometryMap.put("coordinates", getCoordinates(geometry));
return geometryMap;
} catch (Exception e) {
return createEmptyMultiPolygon();
}
}
/**
* 直接获取几何坐标避免JSON转换
*/
private static List<?> getCoordinates(Geometry geometry) {
List<Object> coordinates = new ArrayList<>();
if (geometry == null) {
return coordinates;
}
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry polygon = geometry.GetGeometryRef(i);
if (polygon == null) continue;
List<Object> polygonCoords = new ArrayList<>();
int ringCount = polygon.GetGeometryCount();
for (int j = 0; j < ringCount; j++) {
Geometry ring = polygon.GetGeometryRef(j);
if (ring == null) continue;
List<List<Double>> ringCoords = new ArrayList<>();
int pointCount = ring.GetPointCount();
for (int k = 0; k < pointCount; k++) {
double[] point = ring.GetPoint(k);
List<Double> pointCoords = new ArrayList<>(2);
pointCoords.add(point[0]);
pointCoords.add(point[1]);
ringCoords.add(pointCoords);
}
polygonCoords.add(ringCoords);
}
coordinates.add(polygonCoords);
}
return coordinates;
}
/**
* 获取字段值、根据字段类型处理
*/
private static Object getFieldValue(Feature feature, int fieldIndex, int fieldType) {
try {
switch (fieldType) {
case ogr.OFTInteger:
return feature.GetFieldAsInteger(fieldIndex);
case ogr.OFTInteger64:
return feature.GetFieldAsInteger64(fieldIndex);
case ogr.OFTReal:
return feature.GetFieldAsDouble(fieldIndex);
case ogr.OFTString:
case ogr.OFTStringList:
case ogr.OFTWideString:
return feature.GetFieldAsString(fieldIndex);
case ogr.OFTDate:
case ogr.OFTTime:
case ogr.OFTDateTime:
return feature.GetFieldAsString(fieldIndex);
default:
// 对于其他类型,统一返回字符串表示
return feature.GetFieldAsString(fieldIndex);
}
} catch (Exception e) {
return feature.GetFieldAsString(fieldIndex);
}
}
/**
* 创建空的 MultiPolygon 几何对象
*/
private static Map<String, Object> createEmptyMultiPolygon() {
Map<String, Object> geometry = new HashMap<>(2);
geometry.put("type", "MultiPolygon");
geometry.put("coordinates", new ArrayList<>());
return geometry;
}
}

View File

@ -1,245 +0,0 @@
package com.yj.earth.common.util;
import cn.hutool.core.lang.UUID;
import java.sql.*;
import java.time.LocalDateTime;
public class SQLiteConverter {
private static final String JDBC_DRIVER = "org.sqlite.JDBC";
// 源数据库和目标数据库路径
private String sourceDbPath;
private String targetDbPath;
// 批处理大小、可根据内存情况调整
private static final int BATCH_SIZE = 100;
public SQLiteConverter(String sourceDbPath, String targetDbPath) {
this.sourceDbPath = sourceDbPath;
this.targetDbPath = targetDbPath;
}
public void convert() {
Connection sourceConn = null;
Connection targetConn = null;
try {
// 加载驱动
Class.forName(JDBC_DRIVER);
// 连接源数据库和目标数据库
sourceConn = DriverManager.getConnection("jdbc:sqlite:" + sourceDbPath);
targetConn = DriverManager.getConnection("jdbc:sqlite:" + targetDbPath);
// 禁用自动提交、以便在出现错误时可以回滚
targetConn.setAutoCommit(false);
// 创建目标表结构
createTargetTables(targetConn);
// 复制并转换数据
copyModeTypesData(sourceConn, targetConn);
copyModelsData(sourceConn, targetConn);
// 为model表添加索引
createModelTableIndexes(targetConn);
// 提交事务
targetConn.commit();
System.out.println("数据库转换成功!");
} catch (Exception e) {
e.printStackTrace();
try {
if (targetConn != null) {
targetConn.rollback();
System.out.println("转换失败、已回滚操作!");
}
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
// 关闭连接
try {
if (sourceConn != null) sourceConn.close();
if (targetConn != null) targetConn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private void createTargetTables(Connection conn) throws SQLException {
System.out.println("开始创建目标表结构...");
Statement stmt = conn.createStatement();
String sql = """
CREATE TABLE "model_type" (
"id" TEXT,
"name" TEXT,
"parent_id" TEXT,
"tree_index" INTEGER,
"created_at" TEXT,
"updated_at" TEXT,
PRIMARY KEY ("id")
);
""";
stmt.execute(sql);
sql = """
CREATE TABLE "model" (
"id" TEXT,
"model_type_id" TEXT,
"model_name" TEXT,
"model_type" TEXT,
"model_data" BLOB,
"poster_type" TEXT,
"poster_data" BLOB,
"created_at" TEXT,
"updated_at" TEXT,
PRIMARY KEY ("id")
);
""";
stmt.execute(sql);
stmt.close();
System.out.println("目标表结构创建完成");
}
/**
* 为 model 表的每个字段创建索引
*/
private void createModelTableIndexes(Connection conn) throws SQLException {
System.out.println("开始为创建索引...");
Statement stmt = conn.createStatement();
String sql = """
CREATE INDEX idx_model_covering ON model(
model_type_id,
id,
model_name,
model_type,
poster_type,
created_at,
updated_at
);
""";
stmt.execute(sql);
stmt.close();
System.out.println("model表索引创建完成");
}
private int getTotalRecords(Connection conn, String tableName) throws SQLException {
PreparedStatement stmt = conn.prepareStatement("SELECT COUNT(*) AS total FROM " + tableName);
ResultSet rs = stmt.executeQuery();
int total = rs.next() ? rs.getInt("total") : 0;
rs.close();
stmt.close();
return total;
}
private void copyModeTypesData(Connection sourceConn, Connection targetConn) throws SQLException {
int totalRecords = getTotalRecords(sourceConn, "mode_types");
System.out.println("开始转换 mode_types 表数据、共" + totalRecords + "条记录");
PreparedStatement sourceStmt = sourceConn.prepareStatement("SELECT * FROM mode_types");
ResultSet rs = sourceStmt.executeQuery();
PreparedStatement targetStmt = targetConn.prepareStatement(
"INSERT INTO model_type (id, name, parent_id, tree_index, created_at, updated_at) " +
"VALUES (?, ?, ?, ?, ?, ?)"
);
int count = 0;
while (rs.next()) {
targetStmt.setString(1, rs.getString("type_id"));
targetStmt.setString(2, rs.getString("type_name"));
targetStmt.setString(3, rs.getString("p_id"));
targetStmt.setInt(4, 0);
targetStmt.setObject(5, LocalDateTime.now());
targetStmt.setObject(6, LocalDateTime.now());
// 添加到批处理
targetStmt.addBatch();
count++;
// 每达到批处理大小或最后一条记录时执行批处理
if (count % BATCH_SIZE == 0 || count == totalRecords) {
targetStmt.executeBatch();
displayProgress(count, totalRecords, "mode_types 表");
}
}
System.out.println("\n成功转换 mode_types 表数据:" + count + "条记录");
rs.close();
sourceStmt.close();
targetStmt.close();
}
private void copyModelsData(Connection sourceConn, Connection targetConn) throws SQLException {
int totalRecords = getTotalRecords(sourceConn, "models");
System.out.println("开始转换 models 表数据、共" + totalRecords + "条记录");
// 对于大字段、使用向前滚动的结果集、避免缓存所有数据
PreparedStatement sourceStmt = sourceConn.prepareStatement(
"SELECT * FROM models",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY
);
sourceStmt.setFetchSize(100);
ResultSet rs = sourceStmt.executeQuery();
PreparedStatement targetStmt = targetConn.prepareStatement(
"INSERT INTO model (id, model_type_id, model_name, model_type, model_data, " +
"poster_type, poster_data, created_at, updated_at) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
int count = 0;
while (rs.next()) {
targetStmt.setString(1, rs.getString("id"));
targetStmt.setString(2, rs.getString("p_id"));
targetStmt.setString(3, rs.getString("model_name"));
targetStmt.setString(4, rs.getString("model_type"));
byte[] dataBytes = rs.getBytes("data");
if (dataBytes != null) {
targetStmt.setBytes(5, dataBytes);
} else {
targetStmt.setNull(5, Types.BLOB);
}
targetStmt.setString(6, rs.getString("poster_type"));
byte[] posterBytes = rs.getBytes("poster");
if (posterBytes != null) {
targetStmt.setBytes(7, posterBytes);
}
targetStmt.setObject(8, LocalDateTime.now());
targetStmt.setObject(9, LocalDateTime.now());
// 添加到批处理
targetStmt.addBatch();
count++;
// 执行批处理
if (count % BATCH_SIZE == 0 || count == totalRecords) {
targetStmt.executeBatch();
displayProgress(count, totalRecords, "models 表");
}
}
System.out.println("\n成功转换 models 表数据:" + count + "条记录");
rs.close();
sourceStmt.close();
targetStmt.close();
}
/**
* 显示进度信息
*/
private void displayProgress(int current, int total, String tableName) {
double percentage = (double) current / total * 100;
// 清除当前行并显示进度
System.out.printf("\r%s: 已完成 %.1f%% (%d/%d条)", tableName, percentage, current, total);
}
public static void main(String[] args) {
// 源数据库路径
String sourcePath = "F:\\公司通用模型库.model";
// 目标数据库路径
String targetPath = "F:\\通用模型库.model";
System.out.println("开始数据库转换...");
System.out.println("源数据库: " + sourcePath);
System.out.println("目标数据库: " + targetPath);
long startTime = System.currentTimeMillis();
// 创建转换器并执行转换
SQLiteConverter converter = new SQLiteConverter(sourcePath, targetPath);
converter.convert();
long endTime = System.currentTimeMillis();
double elapsedTime = (endTime - startTime) / 1000.0;
System.out.printf("转换完成、耗时: %.2f秒%n", elapsedTime);
}
}

View File

@ -89,7 +89,8 @@ public class SQLiteUtil {
stmt.execute("PRAGMA temp_store=MEMORY;"); // 临时表/索引存内存减少磁盘IO
stmt.execute("PRAGMA busy_timeout=2000;"); // 忙等待超时2秒避免瞬时并发锁等待
} catch (SQLException e) {
throw new RuntimeException("初始化SQLite数据源失败路径" + dbFilePath + "", e);
e.printStackTrace();
throw new RuntimeException("初始化SQLite数据源失败路径" + dbFilePath + "+ 原因是:" + e.getMessage());
}
return dataSource;