5分钟学会用中文对话查询数据库,从此告别手写SQL的痛苦,完整代码+实战案例
pom.xml
文件中添加必要的依赖:
JdbcClient
支持application.yaml
文件中配置 DeepSeek API 密钥、聊天模型和数据库连接:
${}
占位符语法从环境变量中读取 API 密钥和数据库配置。
同时指定使用 DeepSeek Chat 模型,并配置 DeepSeek 的 API 基础 URL。DeepSeek 提供了强大的中文和代码理解能力,非常适合文本转 SQL 的场景。数据库配置包括连接 URL、用户名和密码,以及 Flyway 迁移设置。
配置完成后,Spring AI 会自动创建 ChatModel
类型的 Bean,让我们能够与指定的模型进行交互。
src/main/resources/db/migration
目录下创建名为 V01__creating_database_tables.sql
的迁移脚本来建立主要数据库表:
classes
表存储班级信息courses
表存储课程信息students
表存储学生信息,通过外键与班级关联student_courses
表作为学生和课程的多对多关联表,存储选课信息和成绩V02__adding_classes_data.sql
文件来填充 classes
表:
V03__adding_courses_data.sql
迁移脚本填充 courses
表:
V04__adding_students_data.sql
迁移脚本填充 students
表:
src/main/resources
目录下创建 system-prompt.st
文件:
ddl
占位符用于数据库架构。稍后我们会用实际值替换它。
此外,为了进一步保护数据库免受修改,应该只给配置的 MySQL 用户必要的权限。
PromptTemplate
Bean。通过 @Value
注解注入系统提示词模板文件和数据库架构 DDL 迁移脚本。同时,我们用数据库架构内容填充 ddl
占位符。这确保了 LLM 在生成 SQL 查询时始终能访问我们的数据库结构。
接下来,我们使用 ChatModel
和 PromptTemplate
Bean 创建一个 ChatClient
Bean。ChatClient
类是我们与配置的 DeepSeek 模型交互的主要入口点。
SqlGenerator
服务类,将自然语言问题转换为 SQL 查询:
generate()
方法中,我们接收自然语言问题作为输入,使用 chatClient
Bean 将其发送给配置的 LLM。
接下来,我们验证响应确实是 SELECT 查询。如果 LLM 返回 SELECT 查询以外的任何内容,我们抛出带有错误消息的自定义 InvalidQueryException
。
接下来,为了对数据库执行生成的 SQL 查询,创建一个 SqlExecutor
服务类:
execute()
方法中,我们使用 Spring Boot 3.1+ 引入的 JdbcClient
来运行原生 SQL 查询并返回结果。JdbcClient
提供了更简洁的 API 和更好的类型安全性。如果查询没有返回结果,我们抛出自定义的 EmptyResultException
。
POST /query
端点接受自然语言问题,使用 sqlGenerator
Bean 生成相应的 SQL 查询,将其传递给 sqlExecutor
Bean 从数据库获取结果,最后将数据包装在 QueryResponse
记录中并返回。使用 JdbcClient
返回的结果是 List<Map<String, Object>>
格式,每个 Map 代表一行数据,键为列名,值为对应的数据。
application.yaml
文件中启用 SQL 日志记录,以在日志中查看生成的查询:
students
和 classes
表来查找高三年级的学生信息。DeepSeek 模型展现了出色的中文理解和 SQL 生成能力。