SpringAI-mysql

1.实现功能

使用AI实现自动在数据库里建表,实现增删改查操作

使用@Tool配置工具类实现

2.主要步骤

2.1配置xml文件

XML 复制代码
  <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-openai</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.12</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-3-starter</artifactId>
            <version>1.2.20</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

2.2配置application.yml文件

java 复制代码
server:
  port: 8008
spring:
  application:
    name: ai-siliconflow-mcp-glm
  ai:
    openai:
      base-url: https://api.siliconflow.cn
      api-key: 你的硅基流动key
      chat:
        options:
          model: "zai-org/GLM-4.6"
          temperature: 0.7
  datasource:
    password: 123456
    username: root
    url: jdbc:mysql://localhost:3306/jiazhong_2025_2
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      logic-delete-field: status
      logic-delete-value: 0
      logic-not-delete-value: 1

2.3书写bean包

java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.bean;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.type.JdbcType;

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("student")
public class Student implements Serializable {
    @TableId("id")
    private Long id;
    private String name;
    private String password;
    private Character gender;
    @TableField(jdbcType = JdbcType.DATE)
    private String birthday;
    private String phone;
    private String address;
    private Integer status;
}

2.4书写mapper包

因为没有建表的方法

java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.bean.Student;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface StudentMapper extends BaseMapper<Student> {
    @Insert("${sql}")
    boolean createTable(String sql);
}

2.5service包以及serviceimpl包

2.5.1获取时间

java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service;

import org.springframework.stereotype.Service;

@Service
public interface NowDateService {
    String getNowDate();
}
java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.impl;

import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.NowDateService;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;

@Service
public class NowDateServiceImpl implements NowDateService {
    @Tool(description = "获取当前时间")
    public String getNowDate() {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date());
    }
}

2.5.2雪花算法(实现随机生成id)

java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service;

import org.springframework.stereotype.Service;

@Service
public interface SnowFlakeGenerateIdWorkerService{
    /**
     * 生成默认机器ID的雪花ID(AI 工具方法)
     */
    long generateId();

}
java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.impl;

import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.SnowFlakeGenerateIdWorkerService;
import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.util.SnowflakeUtil;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SnowFlakeGenerateIdWorkerServiceImpl implements SnowFlakeGenerateIdWorkerService {

    @Autowired
    private SnowflakeUtil snowflakeUtil;

    /**
     * AI 工具方法:生成默认机器ID的雪花ID
     * @return 雪花ID(Long类型)
     */
    @Tool(description = "生成分布式唯一雪花ID(使用默认机器ID),返回Long类型的唯一ID")
    @Override
    public long generateId() {
        return snowflakeUtil.nextId();
    }
}
java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.util;

import org.springframework.stereotype.Component;

/**
 * 雪花算法工具类(线程安全,单例)
 */
@Component
public class SnowflakeUtil {
    // 起始时间戳(2026-01-01 00:00:00)
    private static final long START_TIMESTAMP = 1777555200000L;
    private static final long WORKER_ID_BITS = 10L;
    private static final long SEQUENCE_BITS = 12L;
    private static final long MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1;
    private static final long MAX_SEQUENCE = (1 << SEQUENCE_BITS) - 1;
    private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
    private static final long TIMESTAMP_SHIFT = WORKER_ID_BITS + SEQUENCE_BITS;

    private final long workerId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeUtil() {
        this(0L);
    }

    public SnowflakeUtil(long workerId) {
        if (workerId < 0 || workerId > MAX_WORKER_ID) {
            throw new IllegalArgumentException("Worker ID 超出范围(0-" + MAX_WORKER_ID + ")");
        }
        this.workerId = workerId;
    }

    public synchronized long nextId() {
        long currentTimestamp = System.currentTimeMillis();
        if (currentTimestamp < lastTimestamp) {
            throw new RuntimeException("时钟回拨,拒绝生成ID!当前时间:" + currentTimestamp + ",上一次时间:" + lastTimestamp);
        }
        if (currentTimestamp == lastTimestamp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;
            if (sequence == 0) {
                currentTimestamp = waitNextTimestamp(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = currentTimestamp;
        return ((currentTimestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT)
                | (workerId << WORKER_ID_SHIFT)
                | sequence;
    }

    private long waitNextTimestamp(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }

    public String parseId(long id) {
        long timestamp = (id >> TIMESTAMP_SHIFT) + START_TIMESTAMP;
        long workerId = (id >> WORKER_ID_SHIFT) & MAX_WORKER_ID;
        long sequence = id & MAX_SEQUENCE;
        return String.format("ID:%d -> 时间戳:%d(%tF %<tT),机器ID:%d,序列号:%d",
                id, timestamp, timestamp, workerId, sequence);
    }
}

2.5.3实现数据库建表、增删查改

java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.bean.Student;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public interface StudentService extends IService<Student> {

    boolean createTable(String sql);
    boolean saveStudent(Student student);
    boolean saveBatchStudent(List<Student> list);
    boolean updateStudent(Student student);
    boolean deleteStudent(Student student);
    List<Student> findAll();
}
java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.bean.Student;
import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.mapper.StudentMapper;
import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper,Student> implements StudentService {
    //创建表的工具
    @Tool(description = "根据方法的参数创建一张表")
    public boolean createTable(@ToolParam(description = "建表语句") String sql) {
        log.info("调用了创建表的工具:{}",sql);
        return getBaseMapper().createTable(sql);
    }
    //新增数据工具
    @Tool(description = "向表中录入数据")
    public boolean saveStudent(@ToolParam(description = "录入的对象") Student student) {
        return save(student);
    }

    @Tool(description = "批量录入数据")
    public boolean saveBatchStudent(@ToolParam(description = "录入的多个对象") List<Student> list) {
        return saveBatch(list);
    }

    @Tool(description = "修改某个同学的信息")
    public boolean updateStudent(@ToolParam(description = "修改的对象") Student student) {

        return updateById(student);
    }

    @Tool(description = "逻辑删除某个学生")
    public boolean deleteStudent(@ToolParam(description = "要删除的对象")Student student) {
        return removeById(student);
    }

    @Tool(description = "获取所有的学生信息")
    public List<Student> findAll() {
        return list();
    }


}

2.6写config包

java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.config;

import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.NowDateService;
import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.SnowFlakeGenerateIdWorkerService;
import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.StudentService;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChatClientConfig {
    @Resource
    private OpenAiChatModel openAiChatModel;
    @Resource
    private StudentService studentService;
    @Resource
    private NowDateService nowDateService;
    @Resource
    private SnowFlakeGenerateIdWorkerService snowFlakeGenerateIdWorkerService;
    @Bean("openAiChatClient")
    public ChatClient openAiChatClient(){
        return ChatClient.builder(openAiChatModel)
                .defaultTools(studentService,nowDateService,snowFlakeGenerateIdWorkerService)
                .build();
    }
}

2.7书写controller包

java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.controller;

import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.bean.Student;
import com.jiazhong.mingxing.ai.siliconflow.mcp.glm.mysql.service.StudentService;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.List;

@RestController
@RequestMapping("/sql")
public class SqlController {
    @Resource
    private ChatClient openAiChatClient;
    @Autowired
    private StudentService studentService;

    @GetMapping(value = "/create",produces = "text/html;charset=utf-8")
    public Flux<String> create(@RequestParam("question") String question){
        return openAiChatClient.prompt(
                        """
                                ##请根据以下上下文操作
                                1. 创建表语句根据Student类为模版生成
                                2. 如果这张表存在,则不新建并返回内容
                                3. 如果创建表时出错,返回错误信息
                                ##Student类的源码如下:
                                ```java
                                @TableName("student")
                                public class Student implements Serializable {
                                    @TableId("id")
                                    private Long id;
                                    private String name;
                                    private String password;
                                    private Character gender;
                                    @TableField(jdbcType = JdbcType.DATE)
                                    private String birthday;
                                    private String phone;
                                    private String address;
                                    private Integer status;
                                }
                                """
                )
                .user(question)
                .stream().content();
    }
    @GetMapping(value = "/insert",produces = "text/html;charset=utf-8")
    public Flux<String> insert(@RequestParam("question") String question){
        return openAiChatClient.prompt(
                        """
                                ##请根据如下上下文执行添加
                                1. 主键id通过雪花算法生成
                                2. 密码需要通过md5进行加密操作
                                3. 如果密码未赋值,默认密码是123456
                                4. 默认性别是男
                                5. 手机号唯一,不能重复
                                6. 如果没有给手机号设置为null
                                6. 如果录入失败,请返回失败原因
                                """
                )
                .user(question)
                .stream().content();
    }
    @GetMapping(value = "/batch_insert", produces = "text/html;charset=utf-8")
    public Flux<String> batchInsert(@RequestParam("question") String question) {
        return openAiChatClient.prompt("""
                            ##请根据如下上下文执行添加
                            1. 主键id通过雪花算法生成
                            2. 密码需要通过md5进行加密操作
                            3. 如果密码未赋值,默认密码是123456
                            4. 手机号唯一,不能重复
                            5. 如果录入失败,请返回失败原因
                        """)
                .user(question)
                .stream().content();
    }
    @GetMapping(value = "/find_all_1",produces = "text/html;charset=utf-8")
    public Flux<String> findAll1(@RequestParam("question") String question){
        return openAiChatClient.prompt(
                        """
                                ##请根据如下上下文执行查询
                                1. 返回的结果是一个HTML页面
                                2. 内容以表格的形式体现
                                3. 数据仅从数据库的表格中获取
                                """
                )
                .user(question)
                .stream().content();
    }
    @GetMapping(value = "/find_all_2",produces = "application/json;chaset=utf-8")
    public List<Student> findAll2(@RequestParam("question") String question){
        return openAiChatClient.prompt(
                        """
                                ##请根据如下上下文执行查询
                                1. 返回的结果是一个HTML页面
                                2. 内容以表格的形式体现
                                3. 数据仅从数据库的表格中获取
                                """
                )
                .user(question)
                .call().entity(new ParameterizedTypeReference<List<Student>>() {});
    }
    @GetMapping(value = "/find_all_3",produces = "application/json;charset=utf-8")
    public List<Student> findAll3(){
        return studentService.findAll();
    }
    @GetMapping(value = "/update",produces = "application/json;chaset=utf-8")
    public Flux<String> update(@RequestParam("question") String question){
        return openAiChatClient.prompt(
                        """
                                ##请根据如下上下文执行查询
                                1. 输出是否已经修改好
                                2.给出修改好后的数据
                                3. 数据仅从数据库的表格中获取
                                """
                )
                .user(question)
                .stream().content();
    }
    @GetMapping(value = "/delete",produces = "application/json;chaset=utf-8")
    public Flux<String> delete(@RequestParam("question") String question){
        return openAiChatClient.prompt(
                        """
                                ##请根据如下上下文执行查询
                                1.逻辑删除是将statue由0变为1 
                                2.输出是否已经删除好
                                2. 给出逻辑删除好后的数据
                                3. 数据仅从数据库的表格中获取
                                """
                )
                .user(question)
                .stream().content();
    }
}
相关推荐
@小匠3 小时前
Read Frog:一款开源的 AI 驱动浏览器语言学习扩展
人工智能·学习
小猿姐3 小时前
实测对比:哪款开源 Kubernetes MySQL Operator 最值得用?(2026 深度评测)
数据库·mysql·云原生
一灯架构5 小时前
90%的人答错!一文带你彻底搞懂ArrayList
java·后端
倔强的石头_5 小时前
从 “存得下” 到 “算得快”:工业物联网需要新一代时序数据平台
数据库
网教盟人才服务平台6 小时前
“方班预备班盾立方人才培养计划”正式启动!
大数据·人工智能
Y4090016 小时前
【多线程】线程安全(1)
java·开发语言·jvm
芯智工坊6 小时前
第15章 Mosquitto生产环境部署实践
人工智能·mqtt·开源
菜菜艾6 小时前
基于llama.cpp部署私有大模型
linux·运维·服务器·人工智能·ai·云计算·ai编程
TDengine (老段)6 小时前
TDengine IDMP 可视化 —— 分享
大数据·数据库·人工智能·时序数据库·tdengine·涛思数据·时序数据
小真zzz6 小时前
搜极星:第三方多平台中立GEO洞察专家全面解析
人工智能·搜索引擎·seo·geo·中立·第三方平台