统一环境:IDEA2026.1.1、JDK21、SpringBoot3.5.14、SpringAI1.1.6、智谱glm-4-flash、MySQL8.0

前置阅读:已掌握 Spring AI 分层记忆架构、InMemory内存记忆、MessageWindow滑动窗口机制

一、前言

上一篇我们彻底吃透了 Spring AI 官方标准记忆架构,基于内存存储实现了多轮上下文对话、会话隔离、消息窗口裁剪等核心能力。

但内存记忆存在致命短板:基于JVM内存存储,项目重启记忆全部丢失、不支持多实例集群共享,仅能用于本地开发测试,完全无法上线生产环境。

为了解决记忆持久化问题,Spring AI 官方提供了JdbcChatMemoryRepository 数据库存储方案,适配MySQL、PostgreSQL等主流关系型数据库。

本篇我们基于 MySQL + JDBC持久化记忆 + 滑动窗口策略 完成架构升级,实现:服务重启记忆不丢失、多实例集群共享、会话数据持久化归档,搭建稳定可靠的企业级对话记忆能力。

二、JdbcChatMemoryRepository 核心介绍

2.1 组件概念

JdbcChatMemoryRepository 是 Spring AI 官方提供的关系型数据库持久化仓库,实现了 ChatMemoryRepository 顶层存储接口,专门用于将对话消息持久化到数据库,替代临时的内存存储。

完美延续 Spring AI 策略与存储解耦的架构设计:上层记忆策略(MessageWindowChatMemory)完全不用改动,仅替换底层存储实现,即可完成持久化升级。

2.2 核心优势(对比内存存储)

  • 持久化存储:对话数据落库,服务重启、宕机重启记忆永不丢失

  • 集群共享:多实例部署共用同一数据库,实现多节点记忆数据同步

  • 事务可靠:依托Spring事务机制,消息存取数据一致性有保障

  • 多租户隔离:基于conversationId天然支持多用户、多会话隔离

  • 可审计可归档:数据库留存完整对话数据,支持业务复盘、日志审计

2.3 适用场景

中小型AI对话系统、企业级智能客服、后台AI咨询功能、需要数据持久化的生产项目。

三、核心架构回顾

本次升级完全沿用原有架构体系,仅替换存储层实现,无侵入改造:

  • 记忆策略层不变:继续使用 MessageWindowChatMemory 滑动窗口裁剪,控制消息数量,避免上下文膨胀

  • 存储层升级:InMemoryChatMemoryRepository → JdbcChatMemoryRepository(MySQL)

  • 自动装配不变:MessageChatMemoryAdvisor 自动完成消息存取、上下文拼接

这种解耦设计的最大优势:上层业务零改动,按需切换存储方案

四、环境准备与依赖引入

4.1 引入核心Maven依赖

需要新增 Spring AI JDBC记忆仓库、MySQL驱动,pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.14</version>
        <relativePath/>
    </parent>

    <groupId>demo.ai</groupId>
    <artifactId>spring-ai-demo</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.ai.version>1.1.6</spring.ai.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring.ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-client-chat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-zhipuai</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
    </dependencies>

</project>

4.2 配置数据库连接

在 application.yml 中配置MySQL数据源,创建数据库spring_ai

spring:
  ai:
    zhipuai:
      api-key: 4281feecb23exxxxxxx  # 从智谱AI获取的 api-key
      base-url: https://open.bigmodel.cn/api/paas
      chat:
        options:
          model: glm-4-flash
          temperature: 0.7  # 随机性 0-1 越低越严谨
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/spring_ai?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
    username: root    # 数据库用户名
    password: 123456  #你的数据库密码
server:
  servlet:
    # 解决流式输出乱码
    encoding:
      charset: UTF-8        # UTF-8字符集
      force: true           # 强制使用UTF-8
      enabled: true         # 开启 Spring Boot 内置的编码过滤器

五、数据表自动初始化说明

注意:新版本Spring AI存在自动建表失效问题,不会自动生成spring_ai_chat_memory数据表,需要手动执行建表SQL,否则项目启动报错、记忆功能无法使用。下面提供可直接执行的标准建表语句:

CREATE TABLE IF NOT EXISTS spring_ai_chat_memory (
    id BIGINT NOT NULL AUTO_INCREMENT,
    conversation_id VARCHAR(36) NOT NULL,
    content TEXT NOT NULL,
    type VARCHAR(10) NOT NULL,
    timestamp TIMESTAMP NOT NULL,
    PRIMARY KEY (id),
    INDEX idx_conv_ts (conversation_id, timestamp),
    CONSTRAINT type_check CHECK (type IN ('USER', 'ASSISTANT', 'SYSTEM', 'TOOL'))
);

执行上述SQL后,会生成 spring_ai_chat_memory 数据表,用于存储会话ID、对话内容、消息类型、时间戳等全部记忆数据,完全适配JdbcChatMemoryRepository持久化规则。

六、全局配置类改造(核心代码)

仅修改存储层Bean,上层记忆策略、Advisor、ChatClient 配置完全复用,零业务侵入。

package demo.ai.conf;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.jdbc.MysqlChatMemoryRepositoryDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

@Configuration
public class ChatMemoryConfig {

//    /**
//     * 1. 注册内存存储仓库(默认存储方案)
//     */
//    @Bean
//    public InMemoryChatMemoryRepository chatMemoryRepository() {
//        return new InMemoryChatMemoryRepository();
//    }

    /**
     * 1. 升级为JDBC数据库持久化仓库(MySQL方言)
     */
    @Bean
    public JdbcChatMemoryRepository chatMemoryRepository(JdbcTemplate jdbcTemplate) {
        // 指定MySQL方言,适配数据库语法
        return JdbcChatMemoryRepository.builder()
                .jdbcTemplate(jdbcTemplate)
                .dialect(new MysqlChatMemoryRepositoryDialect())
                .build();
    }

//    /**
//     * 2. 注册滑动窗口记忆策略
//     * maxMessages:最大保留消息条数,超出自动裁剪旧消息,保留系统消息
//     */
//    @Bean
//    public MessageWindowChatMemory chatMemory(InMemoryChatMemoryRepository repository) {
//        return MessageWindowChatMemory.builder()
//                .chatMemoryRepository(repository)
//                .maxMessages(10)
//                .build();
//    }
    /**
     * 2. 滑动窗口记忆策略(完全复用,无需改动)
     * 最大保留10条消息,自动裁剪过期消息
     */
    @Bean
    public MessageWindowChatMemory chatMemory(JdbcChatMemoryRepository repository) {
        return MessageWindowChatMemory.builder()
                .chatMemoryRepository(repository)
                .maxMessages(10)
                .build();
    }

    /**
     * 3. 构建自带记忆能力的ChatClient
     * 自动装配记忆顾问,实现上下文自动拼接、自动存储
     */
    @Bean
    public ChatClient chatClient(ChatClient.Builder builder, MessageWindowChatMemory chatMemory) {
        return builder
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
                .build();
    }
}

七、控制器代码(完全复用)

得益于架构解耦,业务控制器无需一行代码改动,自动适配数据库持久化记忆。代码参考前一次教程。

八、核心原理与代码解析

8.1 方言适配机制

MysqlChatMemoryRepositoryDialect 是MySQL专属方言,用于适配MySQL的SQL语法、字段类型、主键规则,Spring AI 同时支持PostgreSQL、SQL Server等多种方言,切换数据库仅需替换方言类。

8.2 自动执行流程

  • 请求触发:携带sessionId的用户提问

  • 前置操作:Advisor从数据库查询该会话历史消息,拼接Prompt

  • 模型调用:发送带上下文的请求,获取AI回复

  • 后置操作:自动将本轮问答更新存入数据库

九、功能测试(核心验证:重启不丢失)

9.1 常规多轮记忆测试

1、首次请求:http://localhost:8080/memory/chat?sessionId=user001&msg=我想咨询内科挂号时间

2、重启系统

3、二次请求:http://localhost:8080/memory/chat?sessionId=user001&msg=我刚刚咨询的是什么科室?

结果:AI正常识别上下文,记忆生效,数据库可查询到对话记录。

9.2 核心持久化测试(重点)

1、停止SpringBoot项目,重启服务

2、再次调用上述上下文提问接口

测试结果:服务重启后,AI依然能记住历史对话,彻底解决内存记忆丢失问题!

9.3 会话隔离测试

不同sessionId完全隔离,各自记忆独立存储,无串台问题,支持多用户同时在线对话。

十、Jdbc持久化记忆优缺点

10.1 优势

  • 数据持久化落库,服务重启、宕机记忆不丢失

  • 支持集群多实例部署,多节点共享对话数据

  • 依托数据库事务,数据安全可靠,支持审计归档

  • 官方原生组件,无第三方依赖,适配Spring生态

  • 架构解耦,上层业务无需改动,平滑升级

10.2 劣势

  • 数据库读写性能有限,高并发场景QPS瓶颈明显

  • 频繁读写数据库,会造成数据库IO压力

  • 不适合超高并发、毫秒级响应的分布式AI对话场景

十一、本期踩坑总结

  • 坑1:数据表不存在:未引入jdbc依赖、未配置数据源,未手动执行建表SQL、新版本自动建表失效,导致数据表不存在

  • 坑2:方言不匹配:MySQL必须指定 MysqlChatMemoryRepositoryDialect,否则SQL语法报错

  • 坑3:记忆不更新:未替换Bean,依然使用内存仓库,导致落库失效

  • 坑4:上下文膨胀:未配置maxMessages,数据库消息数据持续累积,影响查询性能

十二、本篇学习总结

本期完成了 Spring AI 记忆体系的生产级升级,核心收获:

  • 掌握 JdbcChatMemoryRepository 数据库持久化核心原理与实战

  • 深刻体会 Spring AI 存储与策略解耦的优秀架构设计

  • 实现可重启、可集群、可归档的企业级对话记忆

  • 掌握多数据库方言适配、自动建表、窗口裁剪组合用法

  • 区分内存存储与数据库存储的适用场景与性能差异

十三、结语

从内存临时记忆,到MySQL持久化记忆,我们一步步将AI对话能力从“测试Demo”打磨为“生产可用”。JDBC记忆方案足够满足中小型项目的生产需求,架构稳定、维护简单。

但对于大型平台、高并发AI对话系统,Redis分布式记忆才是最终的生产最优解,Spring AI 2.0.x将支持RedisChatMemoryRepository,因此后续不再手写RedisChatMemoryRepository。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐