IotDb的安装和基本使用
一、 安装部署
- 拉取镜像
docker pull apache/iotdb:1.3.5-standalone
- 启动脚本:docker-compose.yml
version: '3.8'
services:
iotdb:
image: apache/iotdb:1.3.5-standalone
container_name: iotdb-springboot
ports:
- "6667:6667" # RPC端口
- "8080:8080" # Web UI端口
- "31999:31999" # InfluxDB端口
environment:
- JAVA_OPTS=-DIOTDB_HOME=/iotdb -Xmx2G -Xms1G
- ENABLE_KERBEROS=false
- IOTDB_CONFIGNODE_CONSENSUS_PROTOCOL_CLASS=standalone
- IOTDB_DATANODE_CONSENSUS_PROTOCOL_CLASS=standalone
- IOTDB_SCHEMA_ENGINE_MODE=Memory
- enable_raft_log_persistence=false
volumes:
- iotdb_data:/iotdb/data
- iotdb_logs:/iotdb/logs
restart: unless-stopped
healthcheck:
test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/localhost/6667 && echo -e '\x00\x00\x00\x01\x00\x00\x00\x00' >&3 && head -c 8 <&3"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- default
二、IDEA 连接 IoTDB
2.1 下载驱动文件
-
添加 IDEA驱动

-
IDEA连接数据库



-
User: root
-
Passwords: your_passwords
-
URL: jdbc:iotdb://your_ip:6667/
-
测试连接按钮,SQL语句执行返回数据有异常,但是没关系,也证明连接成功了
select status from root.test.test

三、基本使用
3.1 基础配置
- 添加pom依赖
<!-- Apache IoTDB 依赖 -->
<dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>iotdb-session</artifactId>
<version>2.0.5</version>
</dependency>
- yaml配置
# IoTDB 配置
iotdb:
host: ${IOTDB_HOST:localhost}
port: ${IOTDB_PORT:6667}
username: ${IOTDB_USERNAME:root}
password: ${IOTDB_PASSWORD:root}
node-urls: "" # 多节点集群URL,用逗号分隔,例如: "host1:6667,host2:6667,host3:6667"
- 创建Java config:IoTDBConfig
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 描述: IoTDB 配置类
*
* @author water
* @version 2.0.5
* @date 2026-01-05
*/
@Component
@ConfigurationProperties(prefix = "iotdb")
public class IoTDBConfig {
private String host = "localhost";
private int port = 6667;
private String username = "root";
private String password = "root";
private String nodeUrls; // 支持多个节点的URL
// getter 和 setter 方法
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNodeUrls() {
return nodeUrls;
}
public void setNodeUrls(String nodeUrls) {
this.nodeUrls = nodeUrls;
}
}
- IOTDB 初始化 :IoTDBInitializer
import com.springboot4.java25.service.IoTDBService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
/**
* 描述: IoTDB 初始化组件,在应用启动时执行必要的初始化操作
*
* @author water
* @version 1.0.0
* @date 2026-01-05
*/
@Component
public class IoTDBInitializer implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(IoTDBInitializer.class);
@Autowired
private IoTDBService ioTDBService;
@Override
public void run(String... args) throws Exception {
logger.info("开始初始化 IoTDB...");
try {
// 创建默认存储组
ioTDBService.createStorageGroup("root.default");
logger.info("IoTDB 初始化完成");
} catch (Exception e) {
logger.error("IoTDB 初始化失败", e);
}
}
}
3.2 应用开发
3.2.1 启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.logging.Logger;
/**
* 描述: 25新特性 介绍Java 25版本的新特性和改进
*
* @author water
* @version 1.0.0
* @date 2025-12-29 11:52
*/
@SpringBootApplication
public class Java25Springboot4Application {
public static final Logger logger = Logger.getLogger(Java25Springboot4Application.class.getName());
public static void main(String[] args) {
SpringApplication.run(Java25Springboot4Application.class, args);
}
}
3.2.2 实体对象 model
package com.springboot4.java25.model;
/**
* 描述: IoTDB 数据模型
*
* @author water
* @version 1.0.0
* @date 2026-01-05
*/
public class IoTDataPoint {
private String deviceId;
private String measurement;
private Object value;
private long timestamp;
public IoTDataPoint() {
}
public IoTDataPoint(String deviceId, String measurement, Object value, long timestamp) {
this.deviceId = deviceId;
this.measurement = measurement;
this.value = value;
this.timestamp = timestamp;
}
// getter 和 setter 方法
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getMeasurement() {
return measurement;
}
public void setMeasurement(String measurement) {
this.measurement = measurement;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
3.2.3 控制器 controller
import com.springboot4.java25.service.IoTDBService;
import org.apache.iotdb.isession.SessionDataSet;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.read.common.Field;
import org.apache.tsfile.read.common.RowRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 描述: IoTDB 控制器,提供 REST API 接口来操作 IoTDB
*
* @author water
* @version 1.0.0
* @date 2026-01-05
*/
@RestController
@RequestMapping("/api/iotdb")
public class IoTDBController {
@Autowired
private IoTDBService ioTDBService;
/**
* 创建数据库
*/
@PostMapping("/database/{database}")
public ResponseEntity<String> createDatabase(@PathVariable String database) {
try {
ioTDBService.createDatabase(database);
return ResponseEntity.ok("数据库 " + database + " 创建成功");
} catch (Exception e) {
return ResponseEntity.badRequest().body("创建数据库失败: " + e.getMessage());
}
}
/**
* 创建数据库 - 通过请求参数
*/
@PostMapping(value = "/database", consumes = {"application/x-www-form-urlencoded", "multipart/form-data"})
public ResponseEntity<String> createDatabaseParam(@RequestParam String database) {
try {
ioTDBService.createDatabase(database);
return ResponseEntity.ok("数据库 " + database + " 创建成功");
} catch (Exception e) {
return ResponseEntity.badRequest().body("创建数据库失败: " + e.getMessage());
}
}
/**
* 创建存储组
*/
@PostMapping("/storagegroup/{storageGroup}")
public ResponseEntity<String> createStorageGroup(@PathVariable String storageGroup) {
try {
ioTDBService.createStorageGroup(storageGroup);
return ResponseEntity.ok("存储组 " + storageGroup + " 创建成功");
} catch (Exception e) {
return ResponseEntity.badRequest().body("创建存储组失败: " + e.getMessage());
}
}
/**
* 创建存储组 - 通过请求参数
*/
@PostMapping(value = "/storagegroup", consumes = {"application/x-www-form-urlencoded", "multipart/form-data"})
public ResponseEntity<String> createStorageGroupParam(@RequestParam String storageGroup) {
try {
ioTDBService.createStorageGroup(storageGroup);
return ResponseEntity.ok("存储组 " + storageGroup + " 创建成功");
} catch (Exception e) {
return ResponseEntity.badRequest().body("创建存储组失败: " + e.getMessage());
}
}
/**
* 插入记录
*/
@PostMapping(value = "/insert", consumes = {"application/json"})
public ResponseEntity<String> insertRecord(@RequestBody IoTDBInsertRequest request) {
try {
ioTDBService.insertRecord(
request.getDeviceId(),
request.getTimestamp(),
request.getMeasurements(),
request.getValues()
);
return ResponseEntity.ok("数据插入成功");
} catch (Exception e) {
return ResponseEntity.badRequest().body("数据插入失败: " + e.getMessage());
}
}
/**
* 插入记录 - 支持表单数据
*/
@PostMapping(value = "/insert", consumes = {"application/x-www-form-urlencoded", "multipart/form-data"})
public ResponseEntity<String> insertRecordForm(
String deviceId,
long timestamp,
@RequestParam List<String> measurements,
@RequestParam List<String> values) {
try {
ioTDBService.insertRecord(deviceId, timestamp, measurements, values);
return ResponseEntity.ok("数据插入成功");
} catch (Exception e) {
return ResponseEntity.badRequest().body("数据插入失败: " + e.getMessage());
}
}
/**
* 批量插入记录
*/
@PostMapping("/insert/batch")
public ResponseEntity<String> insertRecords(@RequestBody IoTDBBatchInsertRequest request) {
try {
ioTDBService.insertRecords(
request.getDeviceIds(),
request.getTimestamps(),
request.getMeasurementsList(),
request.getValuesList()
);
return ResponseEntity.ok("批量数据插入成功");
} catch (Exception e) {
return ResponseEntity.badRequest().body("批量数据插入失败: " + e.getMessage());
}
}
/**
* SELECT * FROM root.ipark.`001`
*
* @param sql 查询语句
* @return 查询结果
*/
@GetMapping("/query")
public ResponseEntity<Object> queryData(@RequestParam String sql) {
try {
// 简单验证SQL,防止SQL注入
if (!isValidQuerySql(sql)) {
return ResponseEntity.badRequest().body("无效的查询语句");
}
SessionDataSet dataSet = ioTDBService.queryData(sql);
// 将结果转换为JSON格式返回
List<Object> result = convertDataSetToJson(dataSet);
dataSet.closeOperationHandle();
return ResponseEntity.ok(result);
} catch (Exception e) {
return ResponseEntity.badRequest().body("查询失败: " + e.getMessage());
}
}
/**
* 执行更安全的查询 - 通过POST请求
*/
@PostMapping(value = "/query", consumes = {"application/json"})
public ResponseEntity<Object> queryDataPost(@RequestBody QueryRequest request) {
try {
String sql = request.getSql();
// 简单验证SQL,防止SQL注入
if (!isValidQuerySql(sql)) {
return ResponseEntity.badRequest().body("无效的查询语句");
}
SessionDataSet dataSet = ioTDBService.queryData(sql);
List<Object> result = convertDataSetToJson(dataSet);
dataSet.closeOperationHandle();
return ResponseEntity.ok(result);
} catch (Exception e) {
return ResponseEntity.badRequest().body("查询失败: " + e.getMessage());
}
}
/**
* 简单验证SQL,防止SQL注入
*
* @param sql SQL语句
* @return 是否合法
*/
private boolean isValidQuerySql(String sql) {
if (sql == null || sql.trim().isEmpty()) {
return false;
}
String upperSql = sql.trim().toUpperCase();
// 只允许SELECT语句
if (!upperSql.startsWith("SELECT")) {
return false;
}
// 检查是否包含潜在的危险关键字
String[] dangerousKeywords = {"DROP", "DELETE", "UPDATE", "INSERT", "CREATE", "ALTER", "TRUNCATE", "EXEC",
"CALL"};
for (String keyword : dangerousKeywords) {
if (upperSql.contains(keyword)) {
return false;
}
}
return true;
}
/**
* 将SessionDataSet转换为JSON格式
*
* @param dataSet SessionDataSet对象
* @return JSON格式数据
* @throws Exception 获取数据时发生的异常
*/
private List<Object> convertDataSetToJson(SessionDataSet dataSet) throws Exception {
List<Object> result = new ArrayList<>();
// 获取列信息
List<String> columnNames = dataSet.getColumnNames();
while (dataSet.hasNext()) {
RowRecord record = dataSet.next();
Map<String, Object> row = new HashMap<>();
// 获取记录中的字段列表
List<Field> fields = record.getFields();
// 处理时间戳
long timestamp = record.getTimestamp();
// 使用UTC时区格式化时间戳
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedTime = sdf.format(new java.util.Date(timestamp));
row.put(columnNames.getFirst(), formattedTime);
// 确保字段数量与列名数量一致
int fieldCount = fields != null ? fields.size() : 0;
int columnCount = columnNames.size();
// 安全地处理字段,避免索引越界
for (int i = 0; i < Math.min(fieldCount, columnCount); i++) {
String columnName = columnNames.get(i + 1);
String value = "";
// 检查字段是否存在
if (fields != null && i < fields.size() && fields.get(i) != null) {
value = fields.get(i).toString();
} else {
value = "null"; // 或者使用适当的默认值
}
row.put(columnName, value);
}
result.add(row);
}
return result;
}
/**
* 查询请求对象
*/
public static class QueryRequest {
private String sql;
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
}
/**
* 创建时间序列
*/
@PostMapping("/timeseries")
public ResponseEntity<String> createTimeseries(@RequestBody IoTDBTimeseriesRequest request) {
try {
ioTDBService.createTimeseries(
request.getPath(),
request.getDataType(),
request.getEncoding(),
request.getCompressor()
);
return ResponseEntity.ok("时间序列创建成功");
} catch (Exception e) {
return ResponseEntity.badRequest().body("时间序列创建失败: " + e.getMessage());
}
}
// 请求对象类
public static class IoTDBInsertRequest {
private String deviceId;
private long timestamp;
private List<String> measurements;
private List<String> values;
// getter 和 setter 方法
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public List<String> getMeasurements() {
return measurements;
}
public void setMeasurements(List<String> measurements) {
this.measurements = measurements;
}
public List<String> getValues() {
return values;
}
public void setValues(List<String> values) {
this.values = values;
}
}
public static class IoTDBBatchInsertRequest {
private List<String> deviceIds;
private List<Long> timestamps;
private List<List<String>> measurementsList;
private List<List<String>> valuesList;
// getter 和 setter 方法
public List<String> getDeviceIds() {
return deviceIds;
}
public void setDeviceIds(List<String> deviceIds) {
this.deviceIds = deviceIds;
}
public List<Long> getTimestamps() {
return timestamps;
}
public void setTimestamps(List<Long> timestamps) {
this.timestamps = timestamps;
}
public List<List<String>> getMeasurementsList() {
return measurementsList;
}
public void setMeasurementsList(List<List<String>> measurementsList) {
this.measurementsList = measurementsList;
}
public List<List<String>> getValuesList() {
return valuesList;
}
public void setValuesList(List<List<String>> valuesList) {
this.valuesList = valuesList;
}
}
public static class IoTDBTimeseriesRequest {
private String path;
private TSDataType dataType;
private String encoding;
private String compressor;
// getter 和 setter 方法
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public TSDataType getDataType() {
return dataType;
}
public void setDataType(TSDataType dataType) {
this.dataType = dataType;
}
public String getEncoding() {
return encoding;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
public String getCompressor() {
return compressor;
}
public void setCompressor(String compressor) {
this.compressor = compressor;
}
}
}
3.2.3 控制器 service
import com.springboot4.java25.config.IoTDBConfig;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.apache.iotdb.isession.SessionDataSet;
import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.session.Session;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.file.metadata.enums.CompressionType;
import org.apache.tsfile.file.metadata.enums.TSEncoding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 描述: IoTDB 服务类,用于处理与 IoTDB 的交互
*
* @author water
* @version 1.0.0
* @date 2026-01-05
*/
@Service
public class IoTDBService {
private static final Logger logger = LoggerFactory.getLogger(IoTDBService.class);
private Session session;
@Autowired
private IoTDBConfig config;
@PostConstruct
public void init() {
try {
Session.Builder builder =
new Session.Builder().host(config.getHost()).port(config.getPort()).username(config.getUsername()).password(config.getPassword());
// 如果配置了多个节点URL
if (config.getNodeUrls() != null && !config.getNodeUrls().isEmpty()) {
String[] nodeUrls = config.getNodeUrls().split(",");
builder.nodeUrls(Arrays.asList(nodeUrls));
}
session = builder.build();
session.open(false);
logger.info("成功连接到 IoTDB 服务器: {}:{}", config.getHost(), config.getPort());
// 测试连接
testConnection();
} catch (IoTDBConnectionException e) {
logger.error("连接 IoTDB 服务器失败: {}:{}", config.getHost(), config.getPort(), e);
}
}
/**
* 测试连接
*/
private void testConnection() {
try {
SessionDataSet dataSet = session.executeQueryStatement("SHOW VERSION");
logger.info("IoTDB 连接测试成功");
dataSet.closeOperationHandle();
} catch (Exception e) {
logger.error("IoTDB 连接测试失败", e);
}
}
@PreDestroy
public void close() {
if (session != null) {
try {
session.close();
logger.info("IoTDB 连接已关闭");
} catch (IoTDBConnectionException e) {
logger.error("关闭 IoTDB 连接时出错", e);
}
}
}
/**
* 创建数据库(存储组)
*
* @param database 数据库名称
* @throws IoTDBConnectionException io 异常
* @throws StatementExecutionException SQL异常
*/
public void createDatabase(String database) throws IoTDBConnectionException, StatementExecutionException {
checkStorageGroupOrDataBase(database);
}
/**
* 插入记录
*/
public void insertRecord(String deviceId, long timestamp, List<String> measurements, List<String> values) throws IoTDBConnectionException, StatementExecutionException {
// 确保设备ID符合IoTDB路径规范 (root.storageGroup.device)
deviceId = normalizeDeviceId(deviceId);
session.insertRecord(deviceId, timestamp, measurements, values);
logger.info("插入记录: 设备={}, 时间戳={}", deviceId, timestamp);
}
/**
* 批量插入记录
*/
public void insertRecords(List<String> deviceIds, List<Long> timestamps, List<List<String>> measurementsList,
List<List<String>> valuesList) throws IoTDBConnectionException,
StatementExecutionException {
// 确保所有设备ID符合IoTDB路径规范 (root.storageGroup.device)
List<String> normalizedDeviceIds = new ArrayList<>();
for (String deviceId : deviceIds) {
normalizedDeviceIds.add(normalizeDeviceId(deviceId));
}
session.insertRecords(normalizedDeviceIds, timestamps, measurementsList, valuesList);
logger.info("批量插入记录: {} 条", deviceIds.size());
}
/**
* 查询数据
*/
public SessionDataSet queryData(String sql) throws IoTDBConnectionException, StatementExecutionException {
logger.info("执行查询: {}", sql);
return session.executeQueryStatement(sql);
}
/**
* 创建时间序列
*/
public void createTimeseries(String path, TSDataType dataType, String encoding, String compressor) throws IoTDBConnectionException, StatementExecutionException {
session.createTimeseries(path, dataType, TSEncoding.valueOf(encoding), CompressionType.valueOf(compressor));
logger.info("创建时间序列: {}", path);
}
/**
* 使用新API创建时间序列
*/
public void createTimeseriesNewAPI(String path, TSDataType dataType, TSEncoding encoding,
CompressionType compressionType) throws IoTDBConnectionException,
StatementExecutionException {
session.createTimeseries(path, dataType, encoding, compressionType);
logger.info("创建时间序列 (新API): {}", path);
}
/**
* 删除时间序列
*/
public void deleteTimeseries(String path) throws IoTDBConnectionException, StatementExecutionException {
session.deleteTimeseries(path);
logger.info("删除时间序列: {}", path);
}
/**
* 删除存储组
*/
public void deleteStorageGroup(String storageGroup) throws IoTDBConnectionException, StatementExecutionException {
session.deleteStorageGroup(storageGroup);
logger.info("删除存储组: {}", storageGroup);
}
/**
* 创建存储组(数据库)
*
* @param storageGroup 存储组名称(storageGroup /数据库)
* @throws IoTDBConnectionException io 异常
* @throws StatementExecutionException SQL异常
*/
public void createStorageGroup(String storageGroup) throws IoTDBConnectionException, StatementExecutionException {
checkStorageGroupOrDataBase(storageGroup);
}
/**
* 检查存储组(数据库),并创建存储组(数据库)
*
* @param database 存储组名称(storageGroup /数据库)
*/
private void checkStorageGroupOrDataBase(String database) throws IoTDBConnectionException,
StatementExecutionException {
// 在IoTDB中,数据库是通过存储组实现的,必须以root开头
if (!database.startsWith("root.")) {
database = "root." + database;
}
// 检查存储组是否已存在,如果不存在则创建
if (storageGroupNoExists(database)) {
session.setStorageGroup(database);
logger.info("创建数据库(存储组): {}", database);
} else {
logger.info("数据库(存储组)已存在: {}", database);
}
}
/**
* 检查存储组是否存在
*
* @param storageGroup 存储组名称
* @return false表示存储组已存在,true表示存储组不存在
*/
private boolean storageGroupNoExists(String storageGroup) {
try {
SessionDataSet dataSet = session.executeQueryStatement("SHOW STORAGE GROUP");
while (dataSet.hasNext()) {
// 通常SHOW STORAGE GROUP的返回结果中第一列是存储组名称
String existingGroup = dataSet.next().getFields().getFirst().toString();
if (existingGroup.equals(storageGroup)) {
dataSet.closeOperationHandle();
return false;
}
}
dataSet.closeOperationHandle();
} catch (Exception e) {
logger.warn("检查存储组是否存在时出错: {}", e.getMessage());
// 如果查询失败,我们无法确定存储组是否存在,但可以尝试直接创建
// 这里返回true让调用者尝试创建,如果存在则会收到异常
return true;
}
return true;
}
/**
* 规范化设备ID,确保其符合IoTDB路径规范 (root.storageGroup.device)
* 如果设备ID只有两段 (如 root.001),则将其转换为三段 (root.default.001)
* 同时处理路径组件中的特殊字符
*
* @param deviceId 原始设备ID
* @return 符合规范的设备ID
*/
private String normalizeDeviceId(String deviceId) {
// 如果设备ID不以root开头,添加root前缀
if (!deviceId.startsWith("root.")) {
deviceId = "root." + deviceId;
}
// 分割路径以检查层级
String[] parts = deviceId.split("\\.");
// 如果只有两段 (如 root.001),添加默认的存储组名称作为第三段
if (parts.length == 2) {
String deviceName = parts[1];
// 转义可能包含特殊字符的组件
deviceName = escapeNodeName(deviceName);
deviceId = "root.default." + deviceName;
// 确保默认存储组存在
try {
checkStorageGroupOrDataBase("default");
} catch (IoTDBConnectionException | StatementExecutionException e) {
logger.error("创建默认存储组失败: {}", e.getMessage());
}
} else if (parts.length == 3) {
// 如果已经有三层结构,检查存储组是否存在并转义组件
String storageGroupName = parts[1];
String deviceName = parts[2];
// 转义可能包含特殊字符的组件
storageGroupName = escapeNodeName(storageGroupName);
deviceName = escapeNodeName(deviceName);
deviceId = "root." + storageGroupName + "." + deviceName;
try {
checkStorageGroupOrDataBase(storageGroupName);
} catch (IoTDBConnectionException | StatementExecutionException e) {
logger.error("创建存储组 {} 失败: {}", storageGroupName, e.getMessage());
}
} else if (parts.length > 3) {
// 处理更深层级的路径,转义所有组件
StringBuilder sb = new StringBuilder("root.");
for (int i = 1; i < parts.length; i++) {
if (i > 1) sb.append(".");
sb.append(escapeNodeName(parts[i]));
}
deviceId = sb.toString();
// 确保存储组存在(第二段是存储组名)
String storageGroupName = escapeNodeName(parts[1]);
try {
checkStorageGroupOrDataBase(storageGroupName);
} catch (IoTDBConnectionException | StatementExecutionException e) {
logger.error("创建存储组 {} 失败: {}", storageGroupName, e.getMessage());
}
}
return deviceId;
}
/**
* 转义IoTDB路径节点名中的特殊字符
*
* @param nodeName 原始节点名
* @return 转义后的节点名
*/
private String escapeNodeName(String nodeName) {
// 检查节点名是否需要转义
// IoTDB路径节点名应由字母、数字、下划线组成
// 如果包含其他字符(如点号、连字符等),需要用反引号括起来
if (nodeName == null || nodeName.isEmpty()) {
return nodeName;
}
// 检查是否包含特殊字符
if (!nodeName.matches("^[a-zA-Z_][a-zA-Z0-9_]*$")) {
// 如果包含特殊字符,用反引号括起来
// 先转义已有的反引号
nodeName = nodeName.replace("`", "``");
return "`" + nodeName + "`";
}
// 检查是否以数字开头
if (nodeName.length() > 0 && Character.isDigit(nodeName.charAt(0))) {
// 数字开头的节点名需要用反引号括起来
return "`" + nodeName + "`";
}
return nodeName;
}
}


170

被折叠的 条评论
为什么被折叠?



