从零开始:SpringBoot + MyBatis + KingbaseES 实现CRUD操作(超详细入门指南)

引言

刚上手国产数据库 KingbaseES,结果一搜 Spring Boot + MyBatis + KingbaseES 的教程不是寥寥无几,就是看完更迷糊:太水的教不会,太复杂的提不起劲?没关系,今天咱就动手搭一个能增删改查的完整小项目,保证你 30 分钟内把第一个 KingbaseES 应用跑起来。

先说为什么要用这套组合。作为天天写 Java、离不开 Spring Boot 的开发者,我自己折腾 KingbaseES 的时候踩过不少坑:依赖拉不下来、驱动版本对不上、配置老报错......很多人卡在这些细节上就放弃了,挺可惜。于是我把整个搭建过程整理出来,想让你真正体验一下 KingbaseES(也就是大家熟悉的金仓数据库)的味道:国产、稳定、兼容性也不错。接下来就不讲空话,直接开干。

学习之前,我希望大家可以去看下第一期:​​金仓数据库KingbaseES V9R1C10安装教程 - Windows版详细指南 ,先给金仓数据库安装到本地,然后再开始学习。 安装完成后,记得检查服务是否启动,端口是否正确(默认端口是54321)。

第一步:项目骨架搭建

1.1 创建Maven项目

首先,我们需要一个标准的SpringBoot项目结构。如果你用IDEA创建,记得选择Spring Initializr:

xml 复制代码
<!-- pom.xml核心依赖 -->
<dependencies>
    <!-- SpringBoot基础依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- MyBatis官方starter -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.3.1</version>
    </dependency>
    
    <!-- KingbaseES驱动,这个最关键! -->
    <dependency>
        <groupId>cn.com.kingbase</groupId>
        <artifactId>kingbase8</artifactId>
        <version>8.6.0</version>
    </dependency>
    
    <!-- 连接池,HikariCP是SpringBoot默认的,性能杠杠的 -->
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
    </dependency>
</dependencies>

小贴士 :很多新手会混淆MyBatis的依赖,记住一定要用官方的 mybatis-spring-boot-starter ,而不是 mybatis-spring

第二步:数据库配置(重点来了!)

KingbaseES的配置是很多人卡住的地方,其实特别简单:

xml 复制代码
# application.properties
# KingbaseES连接配置
spring.datasource.url=jdbc:kingbase8://127.0.0.1:54321/test
spring.datasource.username=system
spring.datasource.password=system
spring.datasource.driver-class-name=com.kingbase8.Driver

# MyBatis配置
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.example.entity
mybatis.configuration.map-underscore-to-camel-case=true

# 服务器端口
server.port=8888

注意 :KingbaseES的默认端口是54321

第三步:表结构设计

我们先创建一个简单的学生表:

sql 复制代码
-- 创建TB_STUDENT表
CREATE TABLE IF NOT EXISTS TB_STUDENT (
    id BIGSERIAL PRIMARY KEY,  -- 自增主键
    name VARCHAR(100) NOT NULL,  -- 学生姓名
    age INTEGER NOT NULL CHECK (age > 0 AND age < 150),  -- 年龄约束
    sex VARCHAR(10) NOT NULL CHECK (sex IN ('男', '女'))  -- 性别约束
);

-- 插入测试数据
INSERT INTO TB_STUDENT (name, age, sex) VALUES 
('张三', 20, '男'),
('李四', 22, '女'),
('王五', 21, '男');

我们可以通过KStudio工具进行创建

第四步:代码实现

4.1 实体类(Entity)

java 复制代码
package com.example.entity;

public class Student {
    private Long id;
    private String name;
    private Integer age;
    private String sex;
    
    // 构造函数、getter、setter省略...
    
    @Override
    public String toString() {
        return String.format("Student{id=%d, name='%s', age=%d, sex='%s'}", 
                           id, name, age, sex);
    }
}

4.2 Mapper接口

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.mapper.StudentMapper">
    
    <!-- 结果映射 -->
    <resultMap id="BaseResultMap" type="com.example.entity.Student">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <result column="age" property="age" jdbcType="INTEGER"/>
        <result column="sex" property="sex" jdbcType="VARCHAR"/>
    </resultMap>
    
    <!-- 查询所有学生 -->
    <select id="findAll" resultMap="BaseResultMap">
        SELECT id, name, age, sex FROM TB_STUDENT
    </select>
    
    <!-- 根据ID查询学生 -->
    <select id="findById" parameterType="java.lang.Long" resultMap="BaseResultMap">
        SELECT id, name, age, sex FROM TB_STUDENT WHERE id = #{id}
    </select>
    
    <!-- 插入学生 -->
    <insert id="insert" parameterType="com.example.entity.Student" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO TB_STUDENT (name, age, sex) VALUES (#{name}, #{age}, #{sex})
    </insert>
    
    <!-- 更新学生 -->
    <update id="update" parameterType="com.example.entity.Student">
        UPDATE TB_STUDENT SET name = #{name}, age = #{age}, sex = #{sex} WHERE id = #{id}
    </update>
    
    <!-- 删除学生 -->
    <delete id="delete" parameterType="java.lang.Long">
        DELETE FROM TB_STUDENT WHERE id = #{id}
    </delete>
    
</mapper>

4.3 Service层(业务逻辑)

java 复制代码
package com.example.service;

import com.example.entity.Student;
import com.example.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class StudentService {

    @Autowired
    private StudentMapper studentMapper;

    // 查询所有学生
    public List<Student> getAllStudents() {
        return studentMapper.findAll();
    }

    // 根据ID查询学生
    public Student getStudentById(Long id) {
        return studentMapper.findById(id);
    }

    // 添加学生
    public int addStudent(Student student) {
        return studentMapper.insert(student);
    }

    // 更新学生
    public int updateStudent(Student student) {
        return studentMapper.update(student);
    }

    // 删除学生
    public int deleteStudent(Long id) {
        return studentMapper.delete(id);
    }
}

4.4 Controller层(RESTful API)

java 复制代码
package com.example.controller;

import com.example.entity.Student;
import com.example.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/students")
@CrossOrigin(origins = "*")
public class StudentController {

    @Autowired
    private StudentService studentService;

    // 获取所有学生
    @GetMapping
    public List<Student> getAllStudents() {
        return studentService.getAllStudents();
    }

    // 根据ID获取学生
    @GetMapping("/{id}")
    public Student getStudentById(@PathVariable Long id) {
        return studentService.getStudentById(id);
    }

    // 添加学生
    @PostMapping
    public String addStudent(@RequestBody Student student) {
        int result = studentService.addStudent(student);
        return result > 0 ? "添加成功" : "添加失败";
    }

    // 更新学生
    @PutMapping("/{id}")
    public String updateStudent(@PathVariable Long id, @RequestBody Student student) {
        student.setId(id);
        int result = studentService.updateStudent(student);
        return result > 0 ? "更新成功" : "更新失败";
    }

    // 删除学生
    @DeleteMapping("/{id}")
    public String deleteStudent(@PathVariable Long id) {
        int result = studentService.deleteStudent(id);
        return result > 0 ? "删除成功" : "删除失败";
    }
}

第五步:测试验证

APIFOX测试验证 查询所有学生验证:成功! 添加学生验证:成功! 更新学生验证:成功! 删除学生验证:成功!

常见问题解答(FAQ)

Q1:连接数据库的时候报"Connection refused"错误,原因是KingbaseES服务器没有启动或者网络配置有问题,此时需要检查KingbaseES是否运行,端口号是否是默认的54321。 Q2:Mybatis找不到Mapper错误:这个问题非常的常见,解决起来也非常容易。解决方案:启动类上面加MapperScan("com.example.mapper")注解,或者给每个Mapper接口都加上@Mapper注解即可解决。 Q3:查询结果是null:首先需要检查一下数据库的字段名和Java的属性名是不是对不上。如果字段是下划线风格,而属性是驼峰命名法,就需要开启Mybatis的map-underscore-to-camel-case配置。加上这个配置后,字段和属性就能自动匹配了。

写在最后

OK,到目前为止,我们这篇文章就结束啦。从KingbaseES的环境配置到增删改查操作,虽然这些都是基础操作,但是它能为我们后面学习进阶教程打下坚实的基础。所以每一步都不可或缺。如果大家在搭建的过程中有任何问题都可以在评论区留言或者私信小编,我看到后就会立即回复。再次感谢大家的耐心阅读,谢谢大家。

相关推荐
追逐时光者39 分钟前
一款基于 Ant Design 设计语言实现、漂亮的 .NET Avalonia UI 控件库
后端·.net
该用户已不存在3 小时前
这几款Rust工具,开发体验直线上升
前端·后端·rust
用户8356290780513 小时前
C# 从 PDF 提取图片教程
后端·c#
L2ncE3 小时前
高并发场景数据与一致性的简单思考
java·后端·架构
水涵幽树4 小时前
MySQL 时间筛选避坑指南:为什么格式化字符串比较会出错?
数据库·后端·sql·mysql·database
ERP老兵_冷溪虎山4 小时前
从ASCII到Unicode:"国际正则"|"表达式"跨国界实战指南(附四大语言支持对比+中医HIS类比映射表)
后端·面试
HyggeBest4 小时前
Golang 并发原语 Sync Cond
后端·架构·go
老张聊数据集成4 小时前
数据建模怎么做?一文讲清数据建模全流程
后端
颜如玉4 小时前
Kernel bypass技术遥望
后端·性能优化·操作系统