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();
    }
}
相关推荐
Coder_Boy_2 小时前
基于SpringAI的在线考试系统-数据库设计核心业务方案
java·数据库·spring boot·ddd·tdd
考證寶題庫網2 小时前
Designing and Implementing a Microsoft Azure AI Solution 微軟Azure AI-102 認證全攻略
人工智能·microsoft·azure
一嘴一个橘子2 小时前
springmvc 参数校验
java
逄逄不是胖胖2 小时前
《动手学深度学习》-52文本预处理实现
人工智能·pytorch·python·深度学习
Pyeako2 小时前
opencv计算机视觉--图形透视(投影)变换&图形拼接
人工智能·python·opencv·计算机视觉·图片拼接·投影变换·图形透视变换
HZjiangzi2 小时前
怎么用三维扫描做数字孪生工厂?思看科技TrackScan-Sharp方案推荐
人工智能·科技·制造·三维扫描仪
视觉&物联智能2 小时前
【杂谈】-2026年人工智能发展趋势:智能体崛起、行业洗牌与安全挑战
人工智能·安全·llm·aigc·agi·智能体
老陈聊架构2 小时前
『AI编程工具』OpenCode 保姆级安装教程:开源 AI 编程代理入门教程
人工智能·部署·ai编程·安装·oepncode
shehuiyuelaiyuehao2 小时前
String的杂七杂八方法
java·开发语言