generated from guanyuankai/bonus-edge-proxy
Compare commits
2 Commits
5db82885b5
...
f0d47d2ec0
| Author | SHA1 | Date |
|---|---|---|
|
|
f0d47d2ec0 | |
|
|
c9c402d6bc |
|
|
@ -24,6 +24,7 @@ target_include_directories(nlohmann_json INTERFACE
|
|||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../libs # 如果你的 libs 目录有项目自定义头文件
|
||||
|
||||
|
||||
)
|
||||
|
||||
add_library(vehicle_road_lib STATIC
|
||||
|
|
@ -66,6 +67,11 @@ add_library(vehicle_road_lib STATIC
|
|||
src/videoService/video_pipeline.cpp
|
||||
src/yoloDetector/postprocess.cc
|
||||
src/yoloDetector/yolo_detector.cpp
|
||||
#mysql模块
|
||||
src/mysqlManager/mysql_manager.cpp
|
||||
src/mysqlManager/AlarmDao.cpp
|
||||
src/mysqlManager/DeviceIdentificationDao.cpp
|
||||
src/mysqlManager/ResourceFileDao.cpp
|
||||
)
|
||||
|
||||
target_include_directories(vehicle_road_lib PUBLIC
|
||||
|
|
@ -95,6 +101,7 @@ target_link_libraries(vehicle_road_lib PRIVATE
|
|||
absl::synchronization
|
||||
absl::status
|
||||
absl::statusor
|
||||
mysqlcppconn
|
||||
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
{
|
||||
"alarm_rules_path": "alarms.json",
|
||||
"config_base_path": "/app/config/",
|
||||
"data_cache_db_path": "edge_data_cache.db",
|
||||
"data_storage_db_path": "edge_proxy_data.db",
|
||||
"device_id": "rk3588-proxy-002",
|
||||
"log_level": "info",
|
||||
"mqtt_broker": "tcp://localhost:1883",
|
||||
"mqtt_client_id_prefix": "vehicle-road-counter-",
|
||||
"piper_executable_path": "/usr/bin/piper",
|
||||
"piper_model_path": "/app/models/model.onnx",
|
||||
"tcp_server_ports": [12345],
|
||||
"video_config_path": "video_config.json",
|
||||
"web_server_port": 8080,
|
||||
"db_user": "forlinx",
|
||||
"db_pwd": "forlinx",
|
||||
"db_database": "smart-car-dev"
|
||||
}
|
||||
"alarm_rules_path": "alarms.json",
|
||||
"config_base_path": "/app/config/",
|
||||
"data_cache_db_path": "edge_data_cache.db",
|
||||
"data_storage_db_path": "edge_proxy_data.db",
|
||||
"db_database": "smart-car-dev",
|
||||
"db_host": "127.0.0.1",
|
||||
"db_pwd": "forlinx",
|
||||
"db_user": "forlinx",
|
||||
"device_id": "rk3588-proxy-002",
|
||||
"log_level": "info",
|
||||
"mqtt_broker": "tcp://localhost:1883",
|
||||
"mqtt_client_id_prefix": "vehicle-road-counter-",
|
||||
"piper_executable_path": "/usr/bin/piper",
|
||||
"piper_model_path": "/app/models/model.onnx",
|
||||
"tcp_server_ports": [
|
||||
12345
|
||||
],
|
||||
"video_config_path": "video_config.json",
|
||||
"web_server_port": 8080
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ RUN apt-get update && \
|
|||
sudo \
|
||||
build-essential \
|
||||
libmysqlclient-dev \
|
||||
libmysqlcppconn-dev \
|
||||
cmake \
|
||||
git \
|
||||
gdb \
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ bool ConfigManager::save_unlocked() {
|
|||
try {
|
||||
ofs << m_config_json.dump(4);
|
||||
ofs.flush(); // 确保缓冲区刷入内核
|
||||
// 在某些关键系统上,可能还需要 fsync
|
||||
// 在某些关键系统上,可能还需要 fsync
|
||||
} catch (const json::exception& e) {
|
||||
spdlog::error("Failed to serialize config. Error: {}", e.what());
|
||||
return false;
|
||||
|
|
@ -213,4 +213,17 @@ std::string ConfigManager::getPiperModelPath() {
|
|||
}
|
||||
std::string ConfigManager::getVideoConfigPath() {
|
||||
return getConfigBasePath() + get<std::string>("video_config_path", "video_config.json");
|
||||
}
|
||||
|
||||
std::string ConfigManager::getDbUser() {
|
||||
return get<std::string>("db_user", "forlinx");
|
||||
}
|
||||
std::string ConfigManager::getDbPwd() {
|
||||
return get<std::string>("db_pwd", "forlinx");
|
||||
}
|
||||
std::string ConfigManager::getDbHost() {
|
||||
return get<std::string>("db_host", "127.0.0.1");
|
||||
}
|
||||
std::string ConfigManager::getDbName() {
|
||||
return get<std::string>("db_database", "smart-car-dev");
|
||||
}
|
||||
|
|
@ -80,6 +80,11 @@ public:
|
|||
std::string getVideoConfigPath();
|
||||
std::string getConfigFilePath() const;
|
||||
|
||||
std::string getDbUser();
|
||||
std::string getDbPwd();
|
||||
std::string getDbHost();
|
||||
std::string getDbName();
|
||||
|
||||
private:
|
||||
ConfigManager() = default;
|
||||
~ConfigManager() = default;
|
||||
|
|
|
|||
10
src/main.cpp
10
src/main.cpp
|
|
@ -15,13 +15,13 @@
|
|||
#include "deviceManager/device_manager.h"
|
||||
#include "mqtt/mqtt_client.h"
|
||||
#include "mqtt/mqtt_router.h"
|
||||
#include "mysqlManager/mysql_manager.h"
|
||||
#include "network/tcp_server.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "systemMonitor/system_monitor.h"
|
||||
#include "videoService/video_pipeline.hpp"
|
||||
#include "web/web_server.h"
|
||||
|
||||
boost::asio::io_context g_io_context;
|
||||
|
||||
void poll_system_metrics(boost::asio::steady_timer& timer, SystemMonitor::SystemMonitor& monitor,
|
||||
|
|
@ -86,7 +86,13 @@ int main(int argc, char* argv[]) {
|
|||
<< ". Running with defaults, but this may cause issues." << std::endl;
|
||||
}
|
||||
|
||||
auto& config = ConfigManager::getInstance();
|
||||
auto& config = ConfigManager::getInstance(); // 此时完成加载配置文件
|
||||
|
||||
std::string db_user = config.getDbUser();
|
||||
std::string db_pwd = config.getDbPwd();
|
||||
std::string db_host = config.getDbHost();
|
||||
std::string db_database = config.getDbName();
|
||||
MysqlManager::GetInstance()->Initialize(db_host, db_user, db_pwd, db_database);
|
||||
|
||||
try {
|
||||
spdlog::set_level(spdlog::level::from_str(config.getLogLevel()));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
#include "AlarmDao.h"
|
||||
|
||||
#include <cppconn/resultset.h>
|
||||
|
||||
#include "mysql_manager.h"
|
||||
|
||||
// 辅助函数:根据枚举获取对应的 Type 字符串和 Name 描述
|
||||
static void GetAlarmTypeInfo(AlarmType type, std::string& outType, std::string& outName) {
|
||||
if (type == AlarmType::POSITION) {
|
||||
outType = "1";
|
||||
outName = "位置告警"; // 1.位置告警
|
||||
} else if (type == AlarmType::LOW_BATTERY) {
|
||||
outType = "2";
|
||||
outName = "电量不足告警"; // 2.电量不足告警
|
||||
} else {
|
||||
outType = "0";
|
||||
outName = "未知类型";
|
||||
}
|
||||
}
|
||||
|
||||
bool AlarmDao::Insert(const Alarm& alarm) {
|
||||
// alarm_time 使用数据库默认值 (CURRENT_TIMESTAMP),所以 SQL 里不写它
|
||||
std::string sql =
|
||||
"INSERT INTO tb_alarm "
|
||||
"(system_id, alarm_type, alarm_type_name, alarm_content) "
|
||||
"VALUES (?, ?, ?, ?)";
|
||||
|
||||
auto pstmt = MysqlManager::GetInstance()->GetPreparedStatement(sql);
|
||||
if (!pstmt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
pstmt->setInt64(1, alarm.systemId);
|
||||
pstmt->setString(2, alarm.alarmType);
|
||||
pstmt->setString(3, alarm.alarmTypeName);
|
||||
pstmt->setString(4, alarm.alarmContent);
|
||||
|
||||
pstmt->executeUpdate();
|
||||
return true;
|
||||
} catch (sql::SQLException& e) {
|
||||
// 实际开发建议打印 e.what()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool AlarmDao::ReportAlarm(int64_t systemId, AlarmType type, const std::string& content) {
|
||||
Alarm alarm;
|
||||
alarm.systemId = systemId;
|
||||
alarm.alarmContent = content;
|
||||
|
||||
// 自动填充类型和名称
|
||||
GetAlarmTypeInfo(type, alarm.alarmType, alarm.alarmTypeName);
|
||||
|
||||
return Insert(alarm);
|
||||
}
|
||||
|
||||
std::vector<Alarm> AlarmDao::GetBySystemId(int64_t systemId) {
|
||||
std::vector<Alarm> list;
|
||||
std::string sql = "SELECT * FROM tb_alarm WHERE system_id = ? ORDER BY alarm_time DESC";
|
||||
|
||||
auto pstmt = MysqlManager::GetInstance()->GetPreparedStatement(sql);
|
||||
if (!pstmt) {
|
||||
return list;
|
||||
}
|
||||
|
||||
try {
|
||||
pstmt->setInt64(1, systemId);
|
||||
std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
|
||||
|
||||
while (res->next()) {
|
||||
Alarm a;
|
||||
a.alarmId = res->getInt64("alarm_id");
|
||||
a.systemId = res->getInt64("system_id");
|
||||
a.alarmType = res->getString("alarm_type");
|
||||
a.alarmTypeName = res->getString("alarm_type_name");
|
||||
a.alarmTime = res->getString("alarm_time");
|
||||
a.alarmContent = res->getString("alarm_content");
|
||||
|
||||
list.push_back(a);
|
||||
}
|
||||
} catch (sql::SQLException& e) {
|
||||
return list;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Domain.h"
|
||||
|
||||
class AlarmDao {
|
||||
public:
|
||||
// 基础插入方法 (直接存实体)
|
||||
bool Insert(const Alarm& alarm);
|
||||
|
||||
// 【推荐】便捷业务方法
|
||||
// 自动根据 type 枚举填充 alarm_type 和 alarm_type_name
|
||||
bool ReportAlarm(int64_t systemId, AlarmType type, const std::string& content);
|
||||
|
||||
// 根据 system_id 查询告警
|
||||
std::vector<Alarm> GetBySystemId(int64_t systemId);
|
||||
};
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
#include "DeviceIdentificationDao.h"
|
||||
|
||||
#include <cppconn/resultset.h>
|
||||
|
||||
#include "mysql_manager.h"
|
||||
|
||||
static std::string GetCarColorStr(CarColor color) {
|
||||
switch (color) {
|
||||
case CarColor::BLUE:
|
||||
return "1";
|
||||
case CarColor::GREEN:
|
||||
return "2";
|
||||
default:
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
static std::string GetCarTypeStr(CarType type) {
|
||||
switch (type) {
|
||||
case CarType::GASOLINE:
|
||||
return "1";
|
||||
case CarType::ELECTRIC:
|
||||
return "2";
|
||||
default:
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
// --- DAO 实现 ---
|
||||
|
||||
int64_t DeviceIdentificationDao::Insert(const DeviceIdentificationData& data) {
|
||||
std::string sql =
|
||||
"INSERT INTO tb_device_identification_data "
|
||||
"(system_id, identification_location, car_color, car_type) "
|
||||
"VALUES (?, ?, ?, ?)";
|
||||
|
||||
auto pstmt = MysqlManager::GetInstance()->GetPreparedStatement(sql);
|
||||
if (!pstmt) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
// 索引从 1 开始
|
||||
pstmt->setInt64(1, data.systemId);
|
||||
pstmt->setString(2, data.identificationLocation);
|
||||
pstmt->setString(3, data.carColor);
|
||||
pstmt->setString(4, data.carType);
|
||||
|
||||
pstmt->executeUpdate();
|
||||
// 在同一个连接会话中查询 LAST_INSERT_ID() 是安全的
|
||||
std::string idSql = "SELECT LAST_INSERT_ID()";
|
||||
auto idStmt = MysqlManager::GetInstance()->GetPreparedStatement(idSql);
|
||||
if (!idStmt) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::unique_ptr<sql::ResultSet> res(idStmt->executeQuery());
|
||||
if (res->next()) {
|
||||
// 获取第一列数据,即 ID
|
||||
return res->getInt64(1);
|
||||
}
|
||||
|
||||
return -1; // 获取ID失败
|
||||
} catch (sql::SQLException& e) {
|
||||
// 建议记录日志: e.what()
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 参数里不再需要 dataId
|
||||
int64_t DeviceIdentificationDao::ReportIdentification(int64_t systemId, const std::string& location,
|
||||
CarColor color, CarType type) {
|
||||
DeviceIdentificationData data;
|
||||
data.systemId = systemId;
|
||||
data.identificationLocation = location;
|
||||
|
||||
// 转换枚举
|
||||
data.carColor = GetCarColorStr(color);
|
||||
data.carType = GetCarTypeStr(type);
|
||||
|
||||
return Insert(data);
|
||||
}
|
||||
|
||||
std::vector<DeviceIdentificationData> DeviceIdentificationDao::GetBySystemId(int64_t systemId) {
|
||||
std::vector<DeviceIdentificationData> list;
|
||||
std::string sql =
|
||||
"SELECT * FROM tb_device_identification_data "
|
||||
"WHERE system_id = ? ORDER BY identification_time DESC";
|
||||
|
||||
auto pstmt = MysqlManager::GetInstance()->GetPreparedStatement(sql);
|
||||
if (!pstmt) {
|
||||
return list;
|
||||
}
|
||||
|
||||
try {
|
||||
pstmt->setInt64(1, systemId);
|
||||
std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
|
||||
|
||||
while (res->next()) {
|
||||
DeviceIdentificationData d;
|
||||
// 查出来的时候还是能读到 ID 的
|
||||
d.identificationDataId = res->getInt64("identification_data_id");
|
||||
d.systemId = res->getInt64("system_id");
|
||||
d.identificationLocation = res->getString("identification_location");
|
||||
d.identificationTime = res->getString("identification_time");
|
||||
d.carColor = res->getString("car_color");
|
||||
d.carType = res->getString("car_type");
|
||||
|
||||
list.push_back(d);
|
||||
}
|
||||
} catch (sql::SQLException& e) {
|
||||
// Log error
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Domain.h"
|
||||
|
||||
class DeviceIdentificationDao {
|
||||
public:
|
||||
// 插入数据 (无需手动传入 ID,数据库自动生成)
|
||||
int64_t Insert(const DeviceIdentificationData& data);
|
||||
|
||||
// 【推荐】便捷业务方法
|
||||
int64_t ReportIdentification(int64_t systemId, const std::string& location, CarColor color,
|
||||
CarType type);
|
||||
|
||||
// 根据 systemId 查询
|
||||
std::vector<DeviceIdentificationData> GetBySystemId(int64_t systemId);
|
||||
};
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// 对应表: tb_alarm
|
||||
struct Alarm {
|
||||
int64_t alarmId; // alarm_id (PK)
|
||||
int64_t systemId; // system_id (FK)
|
||||
std::string alarmType; // alarm_type ("1", "2")
|
||||
std::string alarmTypeName; // alarm_type_name ("位置告警"...)
|
||||
std::string alarmTime; // alarm_time
|
||||
std::string alarmContent; // alarm_content
|
||||
};
|
||||
|
||||
// 业务枚举,方便调用
|
||||
enum class AlarmType {
|
||||
POSITION = 1, // 位置告警
|
||||
LOW_BATTERY = 2 // 电量不足
|
||||
};
|
||||
//=======================================================================
|
||||
|
||||
// 对应表: tb_device_identification_data
|
||||
struct DeviceIdentificationData {
|
||||
int64_t identificationDataId; // 【注意】非自增,需要手动赋值
|
||||
int64_t systemId;
|
||||
std::string identificationLocation;
|
||||
std::string identificationTime; // 数据库自动生成,插入时可为空
|
||||
std::string carColor; // 存 "1" 或 "2"
|
||||
std::string carType; // 存 "1" 或 "2"
|
||||
};
|
||||
|
||||
// 业务枚举:车辆颜色
|
||||
enum class CarColor {
|
||||
BLUE = 1, // 蓝色
|
||||
GREEN = 2, // 绿色
|
||||
UNKNOWN = 0
|
||||
};
|
||||
|
||||
// 业务枚举:车辆类型
|
||||
enum class CarType {
|
||||
GASOLINE = 1, // 油车
|
||||
ELECTRIC = 2, // 电车
|
||||
UNKNOWN = 0
|
||||
};
|
||||
//=======================================================================
|
||||
|
||||
// 业务枚举:文件/图片类型
|
||||
enum class FileType {
|
||||
ORIGINAL = 1, // 原始图片
|
||||
LABELED = 2, // 打过标签的图片
|
||||
UNKNOWN = 0
|
||||
};
|
||||
|
||||
// 对应表: sys_resource_file
|
||||
struct ResourceFile {
|
||||
int64_t sourceId; // source_id (PK, 自增)
|
||||
std::string sourceTable; // source_table (来源表名,如 "tb_alarm")
|
||||
std::string filePath; // file_path (文件存储路径)
|
||||
std::string sourceFileName; // source_file_name (原始文件名)
|
||||
std::string suffixName; // suffix_name (后缀, 如 .jpg)
|
||||
std::string fileType; // file_type ("1", "2")
|
||||
int64_t businessId; // business_id (关联的业务ID,如 alarm_id)
|
||||
std::string businessType; // business_type (业务类型)
|
||||
|
||||
// 以下字段数据库有默认值,查询时才用到
|
||||
std::string createTime;
|
||||
int64_t createUserId;
|
||||
std::string delFlag; // "0"或"1"
|
||||
};
|
||||
//=======================================================================
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
#include "ResourceFileDao.h"
|
||||
|
||||
#include <cppconn/resultset.h>
|
||||
|
||||
#include "mysql_manager.h"
|
||||
|
||||
// --- 静态辅助函数 ---
|
||||
static std::string GetFileTypeStr(FileType type) {
|
||||
switch (type) {
|
||||
case FileType::ORIGINAL:
|
||||
return "1"; // 1.原始图片
|
||||
case FileType::LABELED:
|
||||
return "2"; // 2.打标签图片
|
||||
default:
|
||||
return "1"; // 默认按原始算
|
||||
}
|
||||
}
|
||||
|
||||
// --- DAO 实现 ---
|
||||
|
||||
bool ResourceFileDao::Insert(const ResourceFile& file) {
|
||||
// source_id 自增,create_time/del_flag 有默认值,无需插入
|
||||
std::string sql =
|
||||
"INSERT INTO sys_resource_file "
|
||||
"(source_table, file_path, source_file_name, suffix_name, "
|
||||
"file_type, business_id, business_type, create_user_id) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
auto pstmt = MysqlManager::GetInstance()->GetPreparedStatement(sql);
|
||||
if (!pstmt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
pstmt->setString(1, file.sourceTable);
|
||||
pstmt->setString(2, file.filePath);
|
||||
pstmt->setString(3, file.sourceFileName);
|
||||
pstmt->setString(4, file.suffixName);
|
||||
pstmt->setString(5, file.fileType);
|
||||
pstmt->setInt64(6, file.businessId);
|
||||
pstmt->setString(7, file.businessType);
|
||||
// create_user_id 暂时给0,如果有登录系统可传入
|
||||
pstmt->setInt64(8, file.createUserId);
|
||||
|
||||
pstmt->executeUpdate();
|
||||
return true;
|
||||
} catch (sql::SQLException& e) {
|
||||
// 建议 log: e.what()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ResourceFileDao::SaveFile(const std::string& sourceTable, int64_t businessId,
|
||||
const std::string& filePath, const std::string& fileName,
|
||||
FileType type) {
|
||||
ResourceFile file;
|
||||
file.sourceTable = sourceTable;
|
||||
file.businessId = businessId;
|
||||
file.filePath = filePath;
|
||||
file.sourceFileName = fileName;
|
||||
file.fileType = GetFileTypeStr(type);
|
||||
|
||||
// 简单的后缀名提取逻辑
|
||||
size_t dotPos = fileName.rfind('.');
|
||||
if (dotPos != std::string::npos) {
|
||||
file.suffixName = fileName.substr(dotPos);
|
||||
} else {
|
||||
file.suffixName = "";
|
||||
}
|
||||
|
||||
// 默认值
|
||||
file.businessType = "default";
|
||||
file.createUserId = 0;
|
||||
|
||||
return Insert(file);
|
||||
}
|
||||
|
||||
std::vector<ResourceFile> ResourceFileDao::GetByBusinessId(int64_t businessId) {
|
||||
std::vector<ResourceFile> list;
|
||||
// 默认只查未删除的 (del_flag = '0')
|
||||
std::string sql =
|
||||
"SELECT * FROM sys_resource_file "
|
||||
"WHERE business_id = ? AND del_flag = '0' "
|
||||
"ORDER BY create_time DESC";
|
||||
|
||||
auto pstmt = MysqlManager::GetInstance()->GetPreparedStatement(sql);
|
||||
if (!pstmt) {
|
||||
return list;
|
||||
}
|
||||
|
||||
try {
|
||||
pstmt->setInt64(1, businessId);
|
||||
std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
|
||||
|
||||
while (res->next()) {
|
||||
ResourceFile f;
|
||||
f.sourceId = res->getInt64("source_id");
|
||||
f.sourceTable = res->getString("source_table");
|
||||
f.filePath = res->getString("file_path");
|
||||
f.sourceFileName = res->getString("source_file_name");
|
||||
f.suffixName = res->getString("suffix_name");
|
||||
f.fileType = res->getString("file_type");
|
||||
f.businessId = res->getInt64("business_id");
|
||||
f.businessType = res->getString("business_type");
|
||||
f.createTime = res->getString("create_time");
|
||||
f.delFlag = res->getString("del_flag");
|
||||
|
||||
list.push_back(f);
|
||||
}
|
||||
} catch (sql::SQLException& e) {
|
||||
// Log error
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Domain.h"
|
||||
|
||||
class ResourceFileDao {
|
||||
public:
|
||||
// 基础插入 (source_id 自增,无需传入)
|
||||
bool Insert(const ResourceFile& file);
|
||||
|
||||
// 【推荐】便捷业务方法
|
||||
// 用于把一个文件关联到某个业务ID上
|
||||
// 例如:SaveFile("tb_alarm", alarmId, "/data/img/1.jpg", FileType::ORIGINAL)
|
||||
bool SaveFile(const std::string& sourceTable, int64_t businessId, const std::string& filePath,
|
||||
const std::string& fileName, FileType type);
|
||||
|
||||
// 根据业务ID查询文件 (比如查某条告警关联的所有图片)
|
||||
std::vector<ResourceFile> GetByBusinessId(int64_t businessId);
|
||||
};
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#include "mysql_manager.h"
|
||||
|
||||
MysqlManager* MysqlManager::instance = nullptr;
|
||||
std::mutex MysqlManager::mtx;
|
||||
|
||||
MysqlManager::MysqlManager() {
|
||||
driver = sql::mysql::get_mysql_driver_instance();
|
||||
}
|
||||
|
||||
MysqlManager* MysqlManager::GetInstance() {
|
||||
if (instance == nullptr) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
if (instance == nullptr) {
|
||||
instance = new MysqlManager();
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool MysqlManager::Initialize(const std::string& h, const std::string& u, const std::string& p,
|
||||
const std::string& db) {
|
||||
this->host = h;
|
||||
this->user = u;
|
||||
this->pass = p;
|
||||
this->dbName = db;
|
||||
|
||||
try {
|
||||
// 建立连接
|
||||
connection.reset(driver->connect(host, user, pass));
|
||||
connection->setSchema(dbName);
|
||||
return true;
|
||||
} catch (sql::SQLException& e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void MysqlManager::CheckConnection() {
|
||||
if (!connection || connection->isClosed()) {
|
||||
// 尝试重连
|
||||
try {
|
||||
connection.reset(driver->connect(host, user, pass));
|
||||
connection->setSchema(dbName);
|
||||
} catch (...) {
|
||||
// 重连失败,实际项目中应记录日志
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<sql::PreparedStatement> MysqlManager::GetPreparedStatement(const std::string& sql) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
CheckConnection();
|
||||
|
||||
try {
|
||||
return std::unique_ptr<sql::PreparedStatement>(connection->prepareStatement(sql));
|
||||
} catch (sql::SQLException& e) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include <mysql_driver.h>
|
||||
#include <mysql_connection.h>
|
||||
#include <cppconn/prepared_statement.h>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class MysqlManager {
|
||||
private:
|
||||
static MysqlManager* instance;
|
||||
static std::mutex mtx;
|
||||
|
||||
sql::mysql::MySQL_Driver* driver;
|
||||
std::unique_ptr<sql::Connection> connection;
|
||||
std::string host;
|
||||
std::string user;
|
||||
std::string pass;
|
||||
std::string dbName;
|
||||
|
||||
// 私有构造
|
||||
MysqlManager();
|
||||
|
||||
public:
|
||||
// 禁止拷贝
|
||||
MysqlManager(const MysqlManager&) = delete;
|
||||
MysqlManager& operator=(const MysqlManager&) = delete;
|
||||
|
||||
static MysqlManager* GetInstance();
|
||||
|
||||
// 初始化连接配置
|
||||
bool Initialize(const std::string& host, const std::string& user,
|
||||
const std::string& pass, const std::string& dbName);
|
||||
|
||||
// 获取预编译语句对象 (核心方法)
|
||||
std::unique_ptr<sql::PreparedStatement> GetPreparedStatement(const std::string& sql);
|
||||
|
||||
// 简单的重连检测
|
||||
void CheckConnection();
|
||||
};
|
||||
Loading…
Reference in New Issue