云计算百科
云计算领域专业知识百科平台

【AI大模型接入SDK】SQLite数据持久化模块整体需求

头像

🎬 个人主页:艾莉丝努力练剑

❄专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》 《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:

在这里插入图片描述


文章目录

  • 1 ~> SQLite数据持久化模块整体需求
    • 1.1 业务目标
    • 1.2 数据库表设计
      • 1.2.1 两张核心数据表
      • 1.2.2 表关联约束
    • 1.3 并发线程安全要求
    • 1.4 模块类职责:`DataManager`
  • 2 ~> 公共数据结构体定义 common.h
    • 2.1 Session会话结构体
  • 3 ~> DataManager头文件 DataManager.h
    • 3.1 完整头文件代码
    • 3.2 接口业务逻辑要点
  • 4 ~> DataManager源文件 DataManager.cpp
    • 4.1 构造函数、析构函数
    • 4.2 数据库初始化 initDatabase
    • 4.3 通用无结果SQL执行工具 executeSQL
    • 4.4 Session会话业务接口实现
      • 4.4.1 insertSession 插入会话
      • 4.4.2 getSession 根据sessionId获取会话(加载消息)
      • 4.4.3 updateSessionTimestamp 更新会话时间戳
      • 4.4.4 deleteSession 删除会话(级联删除消息)
      • 4.4.5 getAllSessionIds 获取全部会话ID(按更新时间倒序)
      • 4.4.6 getAllSessions 获取全部会话元数据,不加载消息
      • 4.4.7 getSessionCount 获取会话总数
    • 4.5 Message消息业务接口实现
      • 4.5.1 insertMessage 插入消息并更新会话时间
      • 4.5.2 getSessionMessages 查询会话全部消息
      • 4.5.3 deleteSessionMessages 手动删除会话消息
  • 5 ~> SQLite C API核心原理与易错点
    • 5.1 sqlite3_prepare_v2
    • 5.2 sqlite3_step
    • 5.3 sqlite3_bind_* 参数绑定
    • 5.4 sqlite3_column_* 获取查询结果
    • 5.5 SQLite外键约束
    • 5.6 线程安全
  • 6 ~> 业务联动逻辑:DataManager与会话管理器结合
    • 6.1 会话管理器SessionManager职责
    • 6.2 数据流转流程
  • 7 ~> 面试高频考点总结
  • 结尾

在这里插入图片描述


1 ~> SQLite数据持久化模块整体需求

1.1 业务目标

将AI聊天SDK的会话Session数据、消息Message数据持久化存储到SQLite嵌入式数据库。

1.2 数据库表设计

1.2.1 两张核心数据表

  • sessions会话表:存储会话元数据
  • messages消息表:存储每一条聊天消息
  • 1.2.2 表关联约束

    • 消息表的session_id作为外键引用会话表主键session_id
    • 外键约束开启ON DELETE CASCADE级联删除:删除会话时,该会话下属全部消息自动删除,保障数据一致性。

    注意:SQLite默认关闭外键约束,打开数据库连接后需要执行PRAGMA foreign_keys = ON;开启外键,否则级联删除不会生效,原笔记遗漏该关键点。

    1.3 并发线程安全要求

    • 多线程同时访问数据库会引发竞争条件,使用std::mutex互斥锁保护全部数据库读写操作。
    • mutable std::mutex _mutex:mutable修饰允许const成员函数内部修改该互斥锁变量。

    1.4 模块类职责:DataManager

    • 管理SQLite数据库连接生命周期
    • 数据库初始化、建表
    • Session会话CRUD操作
    • Message消息CRUD操作
    • 封装通用SQL执行工具函数

    2 ~> 公共数据结构体定义 common.h

    2.1 Session会话结构体

    #pragma once
    #include <string>
    #include <vector>
    #include <ctime>
    #include "common.h"

    namespace ai_chat_sdk
    {
    // 会话信息
    struct Session
    {
    std::string _sessionId; //会话唯一ID
    std::string _modelName; //会话绑定的大模型名称
    std::vector<Message> _messages; //会话下全部消息,内存缓存,数据库分表存储
    std::time_t _createdAt; //会话创建时间戳
    std::time_t _updatedAt; //会话最后更新时间戳

    explicit Session(const std::string& modelName = "")
    : _modelName(modelName), _createdAt(0), _updatedAt(0)
    {}
    };

    // 消息结构体
    struct Message
    {
    std::string _messageId; //消息唯一ID
    std::string _role; //角色 user / assistant / system
    std::string _content; //消息文本内容
    std::time_t _timestamp; //消息发送时间戳

    Message(const std::string& role = "", const std::string& content = "")
    : _role(role), _content(content), _timestamp(0)
    {}
    };
    }


    3 ~> DataManager头文件 DataManager.h

    3.1 完整头文件代码

    #pragma once
    #include <sqlite3.h>
    #include <string>
    #include <mutex>
    #include <vector>
    #include <memory>
    #include "common.h"

    namespace ai_chat_sdk
    {
    class DataManager
    {
    public:
    /**
    * @brief 构造函数:打开/创建SQLite数据库
    * @param dbName sqlite数据库文件路径
    */

    explicit DataManager(const std::string& dbName);

    /**
    * @brief 析构函数:关闭数据库连接,释放资源
    */

    ~DataManager();

    //================ Session会话相关接口 =================
    // 插入一条新会话记录
    bool insertSession(const Session& session);

    // 根据sessionId获取会话元数据,同时加载该会话全部历史消息
    std::shared_ptr<Session> getSession(const std::string& sessionId) const;

    // 更新会话最后更新时间戳
    bool updateSessionTimestamp(const std::string& sessionId, std::time_t timestamp);

    // 删除会话,级联删除会话下所有消息
    bool deleteSession(const std::string& sessionId);

    // 获取全部会话ID列表,按更新时间倒序
    std::vector<std::string> getAllSessionIds() const;

    // 获取全部会话元数据(不预加载消息,按需查询)
    std::vector<std::shared_ptr<Session>> getAllSessions() const;

    // 获取会话总数量
    size_t getSessionCount() const;

    // ================ Message消息相关接口 =================
    /**
    * @brief 插入一条消息记录,同时更新所属会话的update_time时间戳
    * @param sessionId 归属会话ID
    * @param message 待插入消息对象
    */

    bool insertMessage(const std::string& sessionId, const Message& message);

    // 查询指定会话下全部历史消息
    std::vector<Message> getSessionMessages(const std::string& sessionId) const;

    // 手动删除指定会话全部消息(外键级联删除一般不需要调用)
    bool deleteSessionMessages(const std::string& sessionId);

    private:
    // 初始化数据库,创建sessions、messages两张数据表
    bool initDatabase();

    /**
    * @brief 执行不需要返回结果集的SQL语句(CREATE、INSERT、UPDATE、DELETE)
    * @param sql sql语句字符串
    * @return 成功返回true,失败false
    */

    bool executeSQL(const std::string& sql);

    private:
    sqlite3* _db = nullptr; //SQLite数据库连接句柄
    std::string _dbName; //数据库文件名称/路径
    mutable std::mutex _mutex; //线程安全互斥锁,const成员函数可修改
    };
    }

    3.2 接口业务逻辑要点

  • insertMessage插入消息后必须同步更新对应会话****update_time,保证会话列表排序时间正确。
  • getAllSessions批量获取会话时不加载消息列表,避免大量会话时内存爆炸;需要消息再调用getSessionMessages按需加载。
  • getSession单条会话查询时,内部自动调用getSessionMessages填充_messages消息容器。

  • 4 ~> DataManager源文件 DataManager.cpp

    4.1 构造函数、析构函数

    #include "DataManager.h"
    #include "util/myLog.h"
    #include <cinttypes>

    namespace ai_chat_sdk
    {
    DataManager::DataManager(const std::string& dbName)
    : _dbName(dbName), _db(nullptr)
    {
    //打开或者创建sqlite数据库文件
    int rc = sqlite3_open(dbName.c_str(), &_db);
    if (rc != SQLITE_OK)
    {
    ERR("打开数据库失败:{}", sqlite3_errmsg(_db));
    return;
    }
    INFO("打开数据库成功:{}", dbName);

    //【重要】SQLite默认关闭外键约束,必须手动开启,否则ON DELETE CASCADE失效
    executeSQL("PRAGMA foreign_keys = ON;");

    //初始化数据表
    if (!initDatabase())
    {
    sqlite3_close(_db);
    _db = nullptr;
    ERR("初始化数据库表失败");
    }
    }

    DataManager::~DataManager()
    {
    if (_db != nullptr)
    {
    sqlite3_close(_db);
    _db = nullptr;
    }
    }

    4.2 数据库初始化 initDatabase

    bool DataManager::initDatabase()
    {
    // 1. 创建会话表 sessions
    std::string createSessionTable = R"(
    CREATE TABLE IF NOT EXISTS sessions(
    session_id TEXT PRIMARY KEY,
    model_name TEXT NOT NULL,
    create_time INTEGER NOT NULL,
    update_time INTEGER NOT NULL
    );
    )"
    ;
    if (!executeSQL(createSessionTable))
    {
    return false;
    }

    // 2. 创建消息表 messages,设置外键+级联删除
    std::string createMessageTable = R"(
    CREATE TABLE IF NOT EXISTS messages(
    message_id TEXT PRIMARY KEY,
    session_id TEXT NOT NULL,
    role TEXT NOT NULL,
    content TEXT NOT NULL,
    timestamp INTEGER NOT NULL,
    FOREIGN KEY(session_id) REFERENCES sessions(session_id) ON DELETE CASCADE
    );
    )"
    ;
    if (!executeSQL(createMessageTable))
    {
    return false;
    }
    return true;
    }

    4.3 通用无结果SQL执行工具 executeSQL

    用于执行CREATE / INSERT / UPDATE / DELETE,不返回查询结果集

    bool DataManager::executeSQL(const std::string& sql)
    {
    if (_db == nullptr)
    {
    ERR("数据库未初始化");
    return false;
    }
    char* errMsg = nullptr;
    int rc = sqlite3_exec(_db, sql.c_str(), nullptr, nullptr, &errMsg);
    if (rc != SQLITE_OK)
    {
    ERR("执行SQL失败:{}", errMsg);
    sqlite3_free(errMsg); //sqlite分配的错误内存,必须使用sqlite_free释放
    return false;
    }

    return true;
    }

    4.4 Session会话业务接口实现

    4.4.1 insertSession 插入会话

    bool DataManager::insertSession(const Session& session)
    {
    std::lock_guard<std::mutex> lock(_mutex);

    std::string insertSQL = R"(
    INSERT INTO sessions(session_id, model_name, create_time, update_time)
    VALUES (?, ?, ?, ?);
    )"
    ;

    sqlite3_stmt* stmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, insertSQL.c_str(), –1, &stmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("insertSession 预处理SQL失败:{}", sqlite3_errmsg(_db));
    return false;
    }

    //绑定参数,time_t转int64_t存入sqlite INTEGER字段
    sqlite3_bind_text(stmt, 1, session._sessionId.c_str(), –1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 2, session._modelName.c_str(), –1, SQLITE_TRANSIENT);
    sqlite3_bind_int64(stmt, 3, static_cast<int64_t>(session._createdAt));
    sqlite3_bind_int64(stmt, 4, static_cast<int64_t>(session._updatedAt));

    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
    ERR("insertSession 执行SQL失败:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(stmt);
    return false;
    }

    sqlite3_finalize(stmt);
    INFO("insertSession 插入会话成功 sessionId={}", session._sessionId);

    return true;
    }

    4.4.2 getSession 根据sessionId获取会话(加载消息)

    std::shared_ptr<Session> DataManager::getSession(const std::string& sessionId) const
    {
    std::lock_guard<std::mutex> lock(_mutex);

    std::string selectSQL = R"(
    SELECT model_name, create_time, update_time FROM sessions WHERE session_id = ?;
    )"
    ;

    sqlite3_stmt* stmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, selectSQL.c_str(), –1, &stmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("getSession 预处理SQL失败:{}", sqlite3_errmsg(_db));
    return nullptr;
    }

    sqlite3_bind_text(stmt, 1, sessionId.c_str(), –1, SQLITE_TRANSIENT);

    rc = sqlite3_step(stmt);
    if (rc != SQLITE_ROW)
    {
    ERR("getSession 未查询到会话 sessionId={}", sessionId);
    sqlite3_finalize(stmt);
    return nullptr;
    }

    //解析查询行数据
    std::string modelName = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
    int64_t createTime = sqlite3_column_int64(stmt, 1);
    int64_t updateTime = sqlite3_column_int64(stmt, 2);

    auto session = std::make_shared<Session>(modelName);
    session->_sessionId = sessionId;
    session->_createdAt = static_cast<std::time_t>(createTime);
    session->_updatedAt = static_cast<std::time_t>(updateTime);

    sqlite3_finalize(stmt);

    //加载该会话全部历史消息
    session->_messages = getSessionMessages(sessionId);
    INFO("getSession 获取会话成功 sessionId={}", sessionId);
    return session;
    }

    4.4.3 updateSessionTimestamp 更新会话时间戳

    bool DataManager::updateSessionTimestamp(const std::string& sessionId, std::time_t timestamp)
    {
    std::lock_guard<std::mutex> lock(_mutex);

    std::string updateSQL = R"(
    UPDATE sessions SET update_time = ? WHERE session_id = ?;
    )"
    ;

    sqlite3_stmt* stmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, updateSQL.c_str(), –1, &stmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("updateSessionTimestamp 预处理SQL失败:{}", sqlite3_errmsg(_db));
    return false;
    }

    sqlite3_bind_int64(stmt, 1, static_cast<int64_t>(timestamp));
    sqlite3_bind_text(stmt, 2, sessionId.c_str(), –1, SQLITE_TRANSIENT);

    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
    ERR("updateSessionTimestamp 执行SQL失败:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(stmt);
    return false;
    }

    sqlite3_finalize(stmt);
    INFO("updateSessionTimestamp 更新会话时间戳成功 sessionId={}", sessionId);

    return true;
    }

    4.4.4 deleteSession 删除会话(级联删除消息)

    bool DataManager::deleteSession(const std::string& sessionId)
    {
    std::lock_guard<std::mutex> lock(_mutex);

    std::string deleteSQL = R"(
    DELETE FROM sessions WHERE session_id = ?;
    )"
    ;

    sqlite3_stmt* stmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, deleteSQL.c_str(), –1, &stmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("deleteSession 预处理SQL失败:{}", sqlite3_errmsg(_db));
    return false;
    }

    sqlite3_bind_text(stmt, 1, sessionId.c_str(), –1, SQLITE_TRANSIENT);

    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
    ERR("deleteSession 执行SQL失败:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(stmt);
    return false;
    }

    sqlite3_finalize(stmt);
    INFO("deleteSession 删除会话成功 sessionId={}", sessionId);

    return true;
    }

    4.4.5 getAllSessionIds 获取全部会话ID(按更新时间倒序)

    std::vector<std::string> DataManager::getAllSessionIds() const
    {
    std::lock_guard<std::mutex> lock(_mutex);
    std::vector<std::string> result;

    std::string selectSQL = R"(
    SELECT session_id FROM sessions ORDER BY update_time DESC;
    )"
    ;

    sqlite3_stmt* stmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, selectSQL.c_str(), –1, &stmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("getAllSessionIds 预处理SQL失败:{}", sqlite3_errmsg(_db));
    return {};
    }

    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
    {
    std::string sid = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
    result.push_back(sid);
    }

    if (rc != SQLITE_DONE)
    {
    ERR("getAllSessionIds 查询执行异常:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(stmt);
    return {};
    }

    sqlite3_finalize(stmt);
    INFO("getAllSessionIds 获取会话ID列表成功,数量={}", result.size());

    return result;
    }

    4.4.6 getAllSessions 获取全部会话元数据,不加载消息

    std::vector<std::shared_ptr<Session>> DataManager::getAllSessions() const
    {
    std::lock_guard<std::mutex> lock(_mutex);
    std::vector<std::shared_ptr<Session>> result;

    std::string selectSQL = R"(
    SELECT session_id, model_name, create_time, update_time
    FROM sessions
    ORDER BY update_time DESC;
    )"
    ;

    sqlite3_stmt* stmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, selectSQL.c_str(), –1, &stmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("getAllSessions 预处理SQL失败:{}", sqlite3_errmsg(_db));
    return {};
    }

    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
    {
    std::string sid = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
    std::string modelName = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
    int64_t createTime = sqlite3_column_int64(stmt, 2);
    int64_t updateTime = sqlite3_column_int64(stmt, 3);

    auto sess = std::make_shared<Session>(modelName);
    sess->_sessionId = sid;
    sess->_createdAt = static_cast<std::time_t>(createTime);
    sess->_updatedAt = static_cast<std::time_t>(updateTime);
    //此处不加载_messages消息,按需查询
    result.push_back(sess);
    }

    if (rc != SQLITE_DONE)
    {
    ERR("getAllSessions 查询执行异常:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(stmt);
    return {};
    }

    sqlite3_finalize(stmt);
    INFO("getAllSessions 获取全部会话元数据成功,数量={}", result.size());

    return result;
    }

    4.4.7 getSessionCount 获取会话总数

    size_t DataManager::getSessionCount() const
    {
    std::lock_guard<std::mutex> lock(_mutex);

    std::string selectSQL = R"(
    SELECT COUNT(*) FROM sessions;
    )"
    ;

    sqlite3_stmt* stmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, selectSQL.c_str(), –1, &stmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("getSessionCount 预处理SQL失败:{}", sqlite3_errmsg(_db));
    return 0;
    }

    rc = sqlite3_step(stmt);
    if (rc != SQLITE_ROW)
    {
    ERR("getSessionCount 查询执行异常:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(stmt);
    return 0;
    }

    size_t count = static_cast<size_t>(sqlite3_column_int64(stmt, 0));
    sqlite3_finalize(stmt);
    INFO("getSessionCount 获取会话总数={}", count);

    return count;
    }

    4.5 Message消息业务接口实现

    4.5.1 insertMessage 插入消息并更新会话时间

    bool DataManager::insertMessage(const std::string& sessionId, const Message& message)
    {
    std::lock_guard<std::mutex> lock(_mutex);

    //1.插入消息记录
    std::string insertMsgSQL = R"(
    INSERT INTO messages(message_id, session_id, role, content, timestamp)
    VALUES (?, ?, ?, ?, ?);
    )"
    ;

    sqlite3_stmt* insertStmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, insertMsgSQL.c_str(), –1, &insertStmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("insertMessage 插入消息预处理失败:{}", sqlite3_errmsg(_db));
    return false;
    }

    sqlite3_bind_text(insertStmt,1,message._messageId.c_str(),–1,SQLITE_TRANSIENT);
    sqlite3_bind_text(insertStmt,2,sessionId.c_str(),–1,SQLITE_TRANSIENT);
    sqlite3_bind_text(insertStmt,3,message._role.c_str(),–1,SQLITE_TRANSIENT);
    sqlite3_bind_text(insertStmt,4,message._content.c_str(),–1,SQLITE_TRANSIENT);
    sqlite3_bind_int64(insertStmt,5,static_cast<int64_t>(message._timestamp));

    rc = sqlite3_step(insertStmt);
    if (rc != SQLITE_DONE)
    {
    ERR("insertMessage 插入消息执行失败:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(insertStmt);
    return false;
    }

    //2.同步更新会话update_time为消息的时间戳
    std::string updateSessionSQL = R"(
    UPDATE sessions SET update_time = ? WHERE session_id = ?;
    )"
    ;

    sqlite3_stmt* updateStmt = nullptr;
    rc = sqlite3_prepare_v2(_db, updateSessionSQL.c_str(), –1, &updateStmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("insertMessage 更新会话时间预处理失败:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(insertStmt);
    return false;
    }

    sqlite3_bind_int64(updateStmt,1,static_cast<int64_t>(message._timestamp));
    sqlite3_bind_text(updateStmt,2,sessionId.c_str(),–1,SQLITE_TRANSIENT);

    rc = sqlite3_step(updateStmt);
    if (rc != SQLITE_DONE)
    {
    ERR("insertMessage 更新会话时间执行失败:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(insertStmt);
    sqlite3_finalize(updateStmt);
    return false;
    }

    sqlite3_finalize(insertStmt);
    sqlite3_finalize(updateStmt);
    INFO("insertMessage 插入消息成功 messageId={}", message._messageId);

    return true;
    }

    4.5.2 getSessionMessages 查询会话全部消息

    std::vector<Message> DataManager::getSessionMessages(const std::string& sessionId) const
    {
    std::lock_guard<std::mutex> lock(_mutex);
    std::vector<Message> result;

    std::string selectSQL = R"(
    SELECT message_id, role, content, timestamp
    FROM messages
    WHERE session_id = ?;
    )"
    ;

    sqlite3_stmt* stmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, selectSQL.c_str(), –1, &stmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("getSessionMessages 预处理SQL失败:{}", sqlite3_errmsg(_db));
    return {};
    }

    sqlite3_bind_text(stmt, 1, sessionId.c_str(), –1, SQLITE_TRANSIENT);

    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
    {
    Message msg;
    msg._messageId = reinterpret_cast<const char*>(sqlite3_column_text(stmt,0));
    msg._role = reinterpret_cast<const char*>(sqlite3_column_text(stmt,1));
    msg._content = reinterpret_cast<const char*>(sqlite3_column_text(stmt,2));
    msg._timestamp = static_cast<std::time_t>(sqlite3_column_int64(stmt,3));
    result.push_back(msg);
    }

    if (rc != SQLITE_DONE)
    {
    ERR("getSessionMessages 查询异常:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(stmt);
    return {};
    }

    sqlite3_finalize(stmt);
    INFO("getSessionMessages 获取会话消息成功 sessionId={},消息数量={}", sessionId, result.size());

    return result;
    }

    4.5.3 deleteSessionMessages 手动删除会话消息

    业务优先使用会话删除的外键级联删除,此接口为备用接口

    bool DataManager::deleteSessionMessages(const std::string& sessionId)
    {
    std::lock_guard<std::mutex> lock(_mutex);

    std::string deleteSQL = R"(
    DELETE FROM messages WHERE session_id = ?;
    )"
    ;

    sqlite3_stmt* stmt = nullptr;
    int rc = sqlite3_prepare_v2(_db, deleteSQL.c_str(), –1, &stmt, nullptr);
    if (rc != SQLITE_OK)
    {
    ERR("deleteSessionMessages 预处理SQL失败:{}", sqlite3_errmsg(_db));
    return false;
    }

    sqlite3_bind_text(stmt, 1, sessionId.c_str(), –1, SQLITE_TRANSIENT);
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
    ERR("deleteSessionMessages 执行SQL失败:{}", sqlite3_errmsg(_db));
    sqlite3_finalize(stmt);
    return false;
    }

    sqlite3_finalize(stmt);
    INFO("deleteSessionMessages 删除会话全部消息成功 sessionId={}", sessionId);

    return true;
    }
    } //namespace ai_chat_sdk


    5 ~> SQLite C API核心原理与易错点

    5.1 sqlite3_prepare_v2

    • 作用:将SQL文本编译预处理为sqlite3_stmt语句对象,支持参数占位符?
    • 返回值SQLITE_OK代表预处理成功。
    • 用完stmt必须调用sqlite3_finalize释放,否则内存泄漏。

    5.2 sqlite3_step

    返回宏含义
    SQLITE_ROW 查询语句:获取到一行有效结果数据
    SQLITE_DONE 执行完成,没有更多数据;INSERT/UPDATE/DELETE正常完成返回此值

    5.3 sqlite3_bind_* 参数绑定

    • sqlite3_bind_text(stmt, index, str, len, destructor)
      • index占位符下标从1开始,不是0
      • len传-1自动读取c字符串\\0截止
      • SQLITE_TRANSIENT:告诉sqlite内部复制一份字符串副本,外部字符串销毁也安全。
    • sqlite3_bind_int64:C++std::time_t必须强转为int64_t存入SQLite INTEGER字段。

    5.4 sqlite3_column_* 获取查询结果

    • 列下标从0开始,与bind下标不一样,高频踩坑点。
    • sqlite3_column_text返回const unsigned char*,必须reinterpret_cast<const char*>转为C++字符串。

    5.5 SQLite外键约束

    • SQLite默认关闭外键约束,打开数据库连接必须执行PRAGMA foreign_keys = ON;,否则ON DELETE CASCADE级联删除完全失效,原笔记缺失该关键点。
    • 外键约束生效条件:数据库不是内存数据库、WAL/DELETE日志模式、开关PRAGMA打开。

    5.6 线程安全

    • SQLite三种线程模式:Single‑Thread / Multi‑Thread / Serialized。
    • 本项目采用Serialized串行模式,应用层额外加std::mutex做二次防护,保证多线程读写安全。
    • mutable std::mutex:const成员函数内部也可以对锁进行加锁解锁操作。

    6 ~> 业务联动逻辑:DataManager与会话管理器结合

    6.1 会话管理器SessionManager职责

  • 在内存中管理活跃会话;
  • 会话创建、销毁时调用DataManager持久化写入数据库;
  • 程序启动时调用DataManager加载历史会话列表;
  • 每次发送/接收AI消息,调用insertMessage写入消息,接口内部自动更新会话时间戳。
  • 6.2 数据流转流程

  • 新建会话:内存生成Session对象 → DataManager::insertSession()写入sessions表。
  • 发送/收到消息:内存生成Message对象 → DataManager::insertMessage(sessionId, msg)写入messages表,自动更新会话update_time。
  • 打开历史会话:传入sessionId调用getSession(sessionId),加载会话元数据+全部历史消息到内存Session对象。
  • 删除会话:调用deleteSession(sessionId),数据库依靠外键ON DELETE CASCADE自动删除该会话所有消息。
  • 程序启动:调用getAllSessionIds()获取全部会话ID,按需加载会话元数据。

  • 7 ~> 面试高频考点总结

  • 为什么会话和消息分两张表存储?
  • 一对多关系:一个Session对应多条Message;
  • 减少冗余,会话元数据只存储一份;
  • 利用外键级联删除保证数据一致性。
  • 为什么插入消息的时候,必须更新会话update_time?
  • 会话列表按照update_time倒序展示,最新聊天会话排在最上方;新增消息代表会话发生变更,需要刷新会话时间戳。
  • SQLite stmt对象为什么必须sqlite3_finalize?
  • stmt对象是sqlite内部堆内存分配,不释放会造成内存泄漏,长期运行程序内存持续上涨。
  • SQLITE_TRANSIENT的作用是什么?
  • 告诉SQLite需要复制一份字符串副本;当外部传入的字符串生命周期结束销毁,SQLite内部仍然持有有效拷贝,防止野指针。
  • 为什么要用mutable修饰mutex成员变量?
  • const成员函数不允许修改类成员变量;互斥锁加锁解锁需要修改锁内部状态,mutable允许const函数修改该成员。
  • SQLite外键级联删除不生效排查点
  • 是否执行PRAGMA foreign_keys = ON打开开关;
  • 确认建表语句FOREIGN KEY + ON DELETE CASCADE语法正确;
  • 确认不是内存数据库。

  • 结尾

    uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

    艾莉丝努力练剑

    C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主


    👀
    【关注】 跟随我一起深耕技术领域,见证每一次成长。

    ❤️
    【点赞】 让优质内容被更多人看见,让知识传递更有力量。

    ⭐
    【收藏】 把核心知识点存好,在需要时随时查、随时用。

    💬
    【评论】 分享你的经验或疑问,评论区一起交流避坑!

    不要忘记给博主“一键四连”哦!

    “今日练剑达成!”

    “技术之路难免有困惑,但同行的人会让前进更有方向。”

    结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主“一键四连”哦!

    往期回顾:

    【AI大模型接入SDK】SQLite C API编程实战:学生表CRUD案例

    🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡

    ૮₍ ˶ ˊ ᴥ ˋ˶₎ა

    在这里插入图片描述

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 【AI大模型接入SDK】SQLite数据持久化模块整体需求
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!