Java连接电科金仓数据库(KingbaseES)实战指南

Java连接电科金仓数据库(KingbaseES)实战指南
摘要:本文分享了KingbaseES V8.6数据库与SpringBoot 2.7.x框架的集成实战经验。内容包括:1. 环境准备(Ubuntu系统安装配置、驱动获取方式);2. JDBC基础操作(连接、查询、事务处理);3. SpringBoot项目完整配置(pom依赖、数据源配置);4. MyBatis-Plus集成(实体类、Mapper、Service层实现);5. RESTful接口开发示例。文章提供了详细的代码示例,涵盖从数据库安装到应用开发的完整流程,帮助开发者快速实现国产数据库适配。

目录

前言

一、环境准备与驱动获取

1.1 数据库安装与配置

1.2 JDBC驱动获取与配置

1.3 创建测试数据库

二、基础JDBC连接与操作

2.1 最基础的JDBC连接示例

2.2 查询测试

2.3 新增测试

2.4 删除测试

2.5 大数据分配处理

三、Spring Boot集成方案

3.1 完整项目配置

3.2 application.yml配置

3.3 实体类与Mapper

3.4 服务层与控制层

四、总结


前言

最近公司项目需要适配国产数据库,经过调研选择了电科金仓的KingbaseES。前前后后折腾了两周,踩了无数坑,从驱动配置到性能调优,每个环节都有故事。本文基于KingbaseES V8.6版本,JDK 1.8环境,Spring Boot 2.7.x框架,分享完整的实战经验。希望能帮助兄弟们少走弯路。

一、环境准备与驱动获取

1.1 数据库安装与配置

首先需要在服务器上安装KingbaseES数据库。这里以Ubuntu环境为例:

# 创建用户 useradd kingbase passwd kingbase # 创建安装目录 mkdir -p /opt/kingbase/ES/V8 chown -R kingbase:kingbase /opt/kingbase # 解压安装包(假设安装包已经下载到/opt/software) cd /opt/software tar -xvf KingbaseES_V008R006C007B0024_Lin64_single_install.tar.gz # 开始安装 ./setup.sh -i console

安装过程中需要注意:

  • 选择"完全安装",包含所有组件
  • 数据目录建议放在独立磁盘,如/kingbase/data
  • 端口默认54321,如果冲突需要修改
  • 字符集选择UTF8,避免中文乱码

我往期作品有2篇文章分别详细介绍windows10和ubunu系统下安装步骤,大家有需要可以去参考参考:

零改造迁移实录:2000+存储过程从SQL Server滑入KingbaseES V9R4C12的72小时

在Ubuntu服务器上安装KingbaseES V009R002C012(Orable兼容版)数据库过程详细记录

1.2 JDBC驱动获取与配置

Kingbase的JDBC驱动获取比较麻烦,有几种方式:

方式1:官网下载https://www.kingbase.com.cn/download.html 访问电科金仓官网(需注册账号):

wget https://www.kingbase.com.cn/download/jdbc/kingbase8-8.6.0.jar

方式2:安装目录获取 安装完成后,驱动位于:

/opt/kingbase/ES/V8/Interface/jdbc/kingbase8-8.6.0.jar

方式3:Maven仓库(推荐) 如果公司搭建了私有仓库,可以上传后使用:

<dependency> <groupId>cn.com.kingbase</groupId> <artifactId>kingbase8</artifactId> <version>8.6.0</version> </dependency>

1.3 创建测试数据库

个人建议创建一个单独数据库,不然跟之前表有可能跟系统库冲突,如下图:

-- 连接数据库 ksql -U system -d testdb -p 54321 -- 创建测试数据库 CREATE DATABASE devdb WITH OWNER = system ENCODING = 'UTF8' LC_COLLATE = 'zh_CN.UTF-8' LC_CTYPE = 'zh_CN.UTF-8'; -- 切换到新数据库 \c devdb

创建测试表king_user,如下图:

-- 创建测试表 CREATE TABLE IF NOT EXISTS king_user ( user_id BIGSERIAL PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, real_name VARCHAR(50), email VARCHAR(100), phone VARCHAR(20), status SMALLINT DEFAULT 1, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP );

创建对应的索引,方便快速查询,如下所示:

-- 创建索引 CREATE INDEX idx_sys_user_username ON king_user(username); CREATE INDEX idx_sys_user_status ON king_user(status); CREATE INDEX idx_sys_user_create_time ON king_user(create_time); -- 插入测试数据 INSERT INTO king_user (username, password, real_name, email, phone) VALUES ('admin', 'e10adc3949ba59abbe56e057f20f883e', '管理员', '[email protected]', '13800138000'), ('zhangsan', 'e10adc3949ba59abbe56e057f20f883e', '张三', '[email protected]', '13900139000'), ('lisi', 'e10adc3949ba59abbe56e057f20f883e', '李四', '[email protected]', '13700137000');

创建订单表和插入测试数据:

-- 创建订单表 CREATE TABLE IF NOT EXISTS biz_order ( order_id BIGSERIAL PRIMARY KEY, order_no VARCHAR(32) NOT NULL UNIQUE, user_id BIGINT NOT NULL, product_name VARCHAR(200) NOT NULL, quantity INTEGER NOT NULL DEFAULT 1, unit_price DECIMAL(10,2) NOT NULL, total_amount DECIMAL(10,2) NOT NULL, order_status SMALLINT DEFAULT 1, payment_status SMALLINT DEFAULT 0, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_order_user FOREIGN KEY (user_id) REFERENCES king_user(user_id) ); -- 创建订单表索引 CREATE INDEX idx_biz_order_user_id ON biz_order(user_id); CREATE INDEX idx_biz_order_order_no ON biz_order(order_no); CREATE INDEX idx_biz_order_create_time ON biz_order(create_time); -- 插入测试订单数据 INSERT INTO biz_order (order_no, user_id, product_name, quantity, unit_price, total_amount) VALUES ('ORDER202312010001', 2, 'Java编程思想(第4版)', 2, 89.00, 178.00), ('ORDER202312010002', 2, 'Spring实战(第5版)', 1, 99.00, 99.00), ('ORDER202312010003', 3, 'MySQL必知必会', 3, 59.00, 177.00);

二、基础JDBC连接与操作

2.1 最基础的JDBC连接示例

创建一个简单的Java项目,先验证能否正常连接:

package com.example.kingbase; import java.sql.*; import java.util.Properties; /** * KingbaseES基础连接测试 */ public class BasicConnectionTest { // 数据库连接信息 private static final String DB_URL = "jdbc:kingbase8://localhost:54321/devdb"; private static final String DB_USER = "system"; private static final String DB_PASSWORD = "123456"; private static final String DRIVER_CLASS = "com.kingbase8.Driver"; public static void main(String[] args) { // 测试连接 testBasicConnection(); // 测试查询 testQuery(); // 测试插入 testInsert(); // 测试事务 testTransaction(); } /** * 基础连接测试 */ public static void testBasicConnection() { Connection conn = null; try { // 1. 加载驱动 Class.forName(DRIVER_CLASS); System.out.println("驱动加载成功!"); // 2. 获取连接 conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); System.out.println("数据库连接成功!"); // 3. 获取数据库元数据 DatabaseMetaData metaData = conn.getMetaData(); System.out.println("数据库产品名称: " + metaData.getDatabaseProductName()); System.out.println("数据库版本: " + metaData.getDatabaseProductVersion()); System.out.println("驱动版本: " + metaData.getDriverVersion()); System.out.println("用户名: " + metaData.getUserName()); } catch (ClassNotFoundException e) { System.err.println("驱动类找不到: " + e.getMessage()); } catch (SQLException e) { System.err.println("数据库连接失败: " + e.getMessage()); } finally { if (conn != null) { try { conn.close(); System.out.println("数据库连接已关闭!"); } catch (SQLException e) { e.printStackTrace(); } } } } 

2.2 查询测试

/** * 查询测试 */ public static void testQuery() { String sql = "SELECT user_id, username, real_name, email, create_time FROM sys_user WHERE status = ? ORDER BY create_time DESC"; try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setInt(1, 1); try (ResultSet rs = pstmt.executeQuery()) { System.out.println("\n=== 用户列表 ==="); System.out.printf("%-10s %-20s %-20s %-30s %-20s%n", "用户ID", "用户名", "真实姓名", "邮箱", "创建时间"); System.out.println("--------------------------------------------------------------------------------"); while (rs.next()) { System.out.printf("%-10d %-20s %-20s %-30s %-20s%n", rs.getLong("user_id"), rs.getString("username"), rs.getString("real_name"), rs.getString("email"), rs.getTimestamp("create_time")); } } } catch (SQLException e) { System.err.println("查询失败: " + e.getMessage()); } }

2.3 新增测试

 /** * 插入测试 */ public static void testInsert() { String sql = "INSERT INTO sys_user (username, password, real_name, email, phone) VALUES (?, ?, ?, ?, ?)"; try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { // 设置参数 pstmt.setString(1, "wangwu"); pstmt.setString(2, "e10adc3949ba59abbe56e057f20f883e"); pstmt.setString(3, "王五"); pstmt.setString(4, "[email protected]"); pstmt.setString(5, "13600136000"); // 执行插入 int affectedRows = pstmt.executeUpdate(); System.out.println("\n插入成功,影响行数: " + affectedRows); // 获取自动生成的主键 try (ResultSet generatedKeys = pstmt.getGeneratedKeys()) { if (generatedKeys.next()) { long userId = generatedKeys.getLong(1); System.out.println("新插入的用户ID: " + userId); } } } catch (SQLException e) { System.err.println("插入失败: " + e.getMessage()); } }

2.4 删除测试

 /** * 事务测试 */ public static void testTransaction() { String insertUserSql = "INSERT INTO sys_user (username, password, real_name) VALUES (?, ?, ?)"; String insertOrderSql = "INSERT INTO biz_order (order_no, user_id, product_name, quantity, unit_price, total_amount) VALUES (?, ?, ?, ?, ?, ?)"; Connection conn = null; try } catch (SQLException e) { e.printStackTrace(); } } /** * 批量删除 */ public static void batchDelete() { String sql = "DELETE FROM sys_user WHERE username = ?"; try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); PreparedStatement pstmt = conn.prepareStatement(sql)) { conn.setAutoCommit(false); // 删除测试数据 String[] usernames = {"test_user_1", "test_user_2", "test_user_3"}; for (String username : usernames) { pstmt.setString(1, username); pstmt.addBatch(); } int[] results = pstmt.executeBatch(); conn.commit(); System.out.println("批量删除完成,删除条数: " + results.length); } catch (SQLException e) { e.printStackTrace(); } }

2.5 大数据分配处理

/** * 大数据量分批处理 */ public static void largeDataProcessing() { String selectSql = "SELECT user_id, username FROM sys_user WHERE user_id > ? ORDER BY user_id ASC LIMIT ?"; String updateSql = "UPDATE sys_user SET email = ? WHERE user_id = ?"; try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); PreparedStatement selectStmt = conn.prepareStatement(selectSql); PreparedStatement updateStmt = conn.prepareStatement(updateSql)) { conn.setAutoCommit(false); long lastUserId = 0; int batchSize = 1000; boolean hasMoreData = true; while (hasMoreData) { // 查询一批数据 selectStmt.setLong(1, lastUserId); selectStmt.setInt(2, batchSize); List<User> userList = new ArrayList<>(); try (ResultSet rs = selectStmt.executeQuery()) { while (rs.next()) { User user = new User(); user.userId = rs.getLong("user_id"); user.username = rs.getString("username"); userList.add(user); } } if (userList.isEmpty()) { hasMoreData = false; continue; } // 更新这批数据 for (User user : userList) { String newEmail = user.username + "@newdomain.com"; updateStmt.setString(1, newEmail); updateStmt.setLong(2, user.userId); updateStmt.addBatch(); lastUserId = user.userId; } updateStmt.executeBatch(); conn.commit(); updateStmt.clearBatch(); System.out.println("已处理至用户ID: " + lastUserId); } System.out.println("大数据量分批处理完成!"); } catch (SQLException e) { e.printStackTrace(); } }

三、Spring Boot集成方案

3.1 完整项目配置

创建一个Spring Boot项目,完整的配置如下:

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>2.7.18</version> <relativePath/> </parent> <groupId>com.example</groupId> <artifactId>kingbase-demo</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>kingbase-demo</name> <description>人大金仓数据库集成示例</description> <properties> <java.version>11</java.version> <kingbase.version>8.6.0</kingbase.version> <mybatis-plus.version>3.5.3.1</mybatis-plus.version> <druid.version>1.2.20</druid.version> </properties> <dependencies> <!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!-- 人大金仓JDBC驱动 --> <dependency> <groupId>cn.com.kingbase</groupId> <artifactId>kingbase8</artifactId> <version>${kingbase.version}</version> </dependency> <!-- 数据库连接池 - Druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <!-- MyBatis Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> <!-- 测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 工具类 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.22</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

3.2 application.yml配置

server: port: 8080 servlet: context-path: /api spring: application: name: kingbase-demo # 数据源配置 datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.kingbase8.Driver url: jdbc:kingbase8://localhost:54321/devdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: system password: 123456 # Druid连接池配置 druid: initial-size: 10 min-idle: 10 max-active: 100 max-wait: 60000 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 validation-query: SELECT 1 test-while-idle: true test-on-borrow: false test-on-return: false pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 filters: stat,wall,slf4j connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 use-global-data-source-stat: true # MyBatis Plus配置 mybatis-plus: configuration: map-underscore-to-camel-case: true cache-enabled: false call-setters-on-nulls: true jdbc-type-for-null: 'null' log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: ASSIGN_ID logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0 mapper-locations: classpath*:mapper/**/*Mapper.xml # 日志配置 logging: level: com.example.kingbase.mapper: debug org.springframework.jdbc: debug

3.3 实体类与Mapper

这个实体类就是我们上面刚刚创建的表

package com.example.kingbase.entity; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; /** * 用户实体 */ @Data @TableName("king_user") public class SysUser implements Serializable { private static final long serialVersionUID = 1L; /** * 用户ID */ @TableId(value = "user_id", type = IdType.ASSIGN_ID) private Long userId; /** * 用户名 */ @TableField("username") private String username; /** * 密码 */ @TableField("password") private String password; /** * 真实姓名 */ @TableField("real_name") private String realName; /** * 邮箱 */ @TableField("email") private String email; /** * 手机号 */ @TableField("phone") private String phone; /** * 状态 0-禁用 1-启用 */ @TableField("status") private Integer status; /** * 创建时间 */ @TableField(value = "create_time", fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; /** * 更新时间 */ @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime updateTime; /** * 逻辑删除标识 */ @TableField("deleted") @TableLogic private Integer deleted; }

Mapper接口:

package com.example.kingbase.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.kingbase.entity.SysUser; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; /** * 用户Mapper */ @Mapper public interface SysUserMapper extends BaseMapper<SysUser> { /** * 根据用户名模糊查询 */ List<SysUser> selectByUsernameLike(@Param("username") String username); /** * 批量插入用户 */ int batchInsert(@Param("userList") List<SysUser> userList); /** * 根据状态统计用户数量 */ int countByStatus(@Param("status") Integer status); }

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.kingbase.mapper.SysUserMapper"> <select resultType="com.example.kingbase.entity.SysUser"> SELECT user_id, username, password, real_name, email, phone, status, create_time, update_time, deleted FROM sys_user WHERE username LIKE CONCAT('%', #{username}, '%') AND deleted = 0 ORDER BY create_time DESC </select> <insert parameterType="java.util.List"> INSERT INTO sys_user (username, password, real_name, email, phone, status, create_time, update_time, deleted) VALUES <foreach collection="userList" item="user" separator=","> (#{user.username}, #{user.password}, #{user.realName}, #{user.email}, #{user.phone}, #{user.status}, #{user.createTime}, #{user.updateTime}, 0) </foreach> </insert> <select resultType="java.lang.Integer"> SELECT COUNT(1) FROM sys_user WHERE status = #{status} AND deleted = 0 </select> </mapper>

3.4 服务层与控制层

服务接口:

package com.example.kingbase.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.kingbase.entity.SysUser; import java.util.List; /** * 用户服务接口 */ public interface ISysUserService extends IService<SysUser> { /** * 批量保存用户 */ boolean batchSaveUsers(List<SysUser> userList); /** * 根据用户名查询用户 */ List<SysUser> getUsersByUsername(String username); /** * 更新用户状态 */ boolean updateUserStatus(Long userId, Integer status); }

服务实现类,常规操作:

package com.example.kingbase.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.kingbase.entity.SysUser; import com.example.kingbase.mapper.SysUserMapper; import com.example.kingbase.service.ISysUserService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.List; /** * 用户服务实现 */ @Slf4j @Service public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService { @Override @Transactional(rollbackFor = Exception.class) public boolean batchSaveUsers(List<SysUser> userList) { if (userList == null || userList.isEmpty()) { return false; } // 设置默认值 LocalDateTime now = LocalDateTime.now(); for (SysUser user : userList) { if (user.getStatus() == null) { user.setStatus(1); } if (user.getCreateTime() == null) { user.setCreateTime(now); } if (user.getUpdateTime() == null) { user.setUpdateTime(now); } } int insertCount = baseMapper.batchInsert(userList); log.info("批量插入用户完成,插入条数:{}", insertCount); return insertCount == userList.size(); } @Override public List<SysUser> getUsersByUsername(String username) { if (username == null || username.trim().isEmpty()) { return list(); } return baseMapper.selectByUsernameLike(username); } @Override @Transactional(rollbackFor = Exception.class) public boolean updateUserStatus(Long userId, Integer status) { SysUser user = getById(userId); if (user == null) { log.warn("用户不存在,userId:{}", userId); return false; } user.setStatus(status); user.setUpdateTime(LocalDateTime.now()); return updateById(user); } }

控制层,就是我们平常用的controller

package com.example.kingbase.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.example.kingbase.common.Result; import com.example.kingbase.entity.SysUser; import com.example.kingbase.service.ISysUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; /** * 用户管理控制器 */ @Api(tags = "用户管理") @RestController @RequestMapping("/user") public class SysUserController { @Autowired private ISysUserService userService; /** * 分页查询用户 */ @ApiOperation("分页查询用户") @GetMapping("/page") public Result<IPage<SysUser>> getUserPage( @ApiParam("当前页") @RequestParam(defaultValue = "1") Integer current, @ApiParam("每页条数") @RequestParam(defaultValue = "10") Integer size, @ApiParam("用户名") @RequestParam(required = false) String username, @ApiParam("状态") @RequestParam(required = false) Integer status) { Page<SysUser> page = new Page<>(current, size); LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>(); if (username != null && !username.trim().isEmpty()) { queryWrapper.like(SysUser::getUsername, username); } if (status != null) { queryWrapper.eq(SysUser::getStatus, status); } queryWrapper.orderByDesc(SysUser::getCreateTime); IPage<SysUser> userPage = userService.page(page, queryWrapper); return Result.success(userPage); } /** * 根据ID查询用户 */ @ApiOperation("根据ID查询用户") @GetMapping("/{id}") public Result<SysUser> getUserById(@PathVariable Long id) { SysUser user = userService.getById(id); if (user == null) { return Result.error("用户不存在"); } return Result.success(user); } /** * 新增用户 */ @ApiOperation("新增用户") @PostMapping public Result<String> addUser(@RequestBody SysUser user) { if (user.getUsername() == null || user.getUsername().trim().isEmpty()) { return Result.error("用户名不能为空"); } if (user.getPassword() == null || user.getPassword().trim().isEmpty()) { return Result.error("密码不能为空"); } // 检查用户名是否已存在 LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(SysUser::getUsername, user.getUsername()); if (userService.count(queryWrapper) > 0) { return Result.error("用户名已存在"); } // 设置默认值 if (user.getStatus() == null) { user.setStatus(1); } LocalDateTime now = LocalDateTime.now(); user.setCreateTime(now); user.setUpdateTime(now); boolean result = userService.save(user); if (result) { return Result.success("用户新增成功"); } else { return Result.error("用户新增失败"); } } /** * 批量新增用户 */ @ApiOperation("批量新增用户") @PostMapping("/batch") public Result<String> batchAddUsers(@RequestBody List<SysUser> userList) { if (userList == null || userList.isEmpty()) { return Result.error("用户列表不能为空"); } // 校验数据 for (SysUser user : userList) { if (user.getUsername() == null || user.getUsername().trim().isEmpty()) { return Result.error("用户名不能为空"); } if (user.getPassword() == null || user.getPassword().trim().isEmpty()) { return Result.error("密码不能为空"); } } boolean result = userService.batchSaveUsers(userList); if (result) { return Result.success("批量新增用户成功,共" + userList.size() + "条"); } else { return Result.error("批量新增用户失败"); } } /** * 更新用户 */ @ApiOperation("更新用户") @PutMapping("/{id}") public Result<String> updateUser(@PathVariable Long id, @RequestBody SysUser user) { SysUser existingUser = userService.getById(id); if (existingUser == null) { return Result.error("用户不存在"); } // 更新字段 if (user.getRealName() != null) { existingUser.setRealName(user.getRealName()); } if (user.getEmail() != null) { existingUser.setEmail(user.getEmail()); } if (user.getPhone() != null) { existingUser.setPhone(user.getPhone()); } existingUser.setUpdateTime(LocalDateTime.now()); boolean result = userService.updateById(existingUser); if (result) { return Result.success("用户更新成功"); } else { return Result.error("用户更新失败"); } } /** * 更新用户状态 */ @ApiOperation("更新用户状态") @PutMapping("/{id}/status/{status}") public Result<String> updateUserStatus( @PathVariable Long id, @PathVariable Integer status) { if (status != 0 && status != 1) { return Result.error("状态值只能是0或1"); } boolean result = userService.updateUserStatus(id, status); if (result) { return Result.success("用户状态更新成功"); } else { return Result.error("用户状态更新失败"); } } /** * 删除用户 */ @ApiOperation("删除用户") @DeleteMapping("/{id}") public Result<String> deleteUser(@PathVariable Long id) { boolean result = userService.removeById(id); if (result) { return Result.success("用户删除成功"); } else { return Result.error("用户删除失败"); } } /** * 批量删除用户 */ @ApiOperation("批量删除用户") @DeleteMapping("/batch") public Result<String> batchDeleteUsers(@RequestBody List<Long> ids) { if (ids == null || ids.isEmpty()) { return Result.error("用户ID列表不能为空"); } boolean result = userService.removeByIds(ids); if (result) { return Result.success("批量删除用户成功"); } else { return Result.error("批量删除用户失败"); } } /** * 根据用户名查询用户 */ @ApiOperation("根据用户名查询用户") @GetMapping("/search") public Result<List<SysUser>> searchUsers(@RequestParam String username) { List<SysUser> userList = userService.getUsersByUsername(username); return Result.success(userList); } /** * 统计用户数量 */ @ApiOperation("统计用户数量") @GetMapping("/count") public Result<Integer> countUsers(@RequestParam(required = false) Integer status) { int count; if (status == null) { count = userService.count(); } else { count = userService.count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getStatus, status)); } return Result.success(count); } }

编写完就可以用postman去测试咯

四、总结

本文分享了KingbaseES V8.6数据库与SpringBoot 2.7.x框架的集成实战经验。内容包括:1. 环境准备(Ubuntu系统安装配置、驱动获取方式);2. JDBC基础操作(连接、查询、事务处理);3. SpringBoot项目完整配置(pom依赖、数据源配置);4. MyBatis-Plus集成(实体类、Mapper、Service层实现);5. RESTful接口开发示例。文章提供了详细的代码示例,涵盖从数据库安装到应用开发的完整流程,帮助开发者快速实现国产数据库适配。

 编码不易,希望各位点赞支持,也支持我们国产的数据库,纸上得来终觉浅,希望各位大佬也亲自动手尝试一下,如果遇到什么问题欢迎评论区留言交流,相互学习,共同进步~正在走向自律

本文相关《电科金仓》分类链接推荐:

第一章:基础与入门

1、【金仓数据库征文】政府项目数据库迁移:从MySQL 5.7到KingbaseES的蜕变之路

2、【金仓数据库征文】学校AI数字人:从Sql Server到KingbaseES的数据库转型之路

3、电科金仓2025发布会,国产数据库的AI融合进化与智领未来

4、国产数据库逆袭:老邓的“六大不敢替”被金仓逐一破解

5、《一行代码不改动!用KES V9 2025完成SQL Server → 金仓“平替”迁移并启用向量检索》

6、《赤兔引擎×的卢智能体:电科金仓如何用“三骏架构”重塑AI原生数据库一体机》

7、探秘KingbaseES在线体验平台:技术盛宴还是虚有其表?

8、破除“分布式”迷思:回归数据库选型的本质

9、KDMS V4 一键搞定国产化迁移:零代码、零事故、零熬夜——金仓社区发布史上最省心数据库迁移评估神器

10、KingbaseES V009版本发布:国产数据库的新飞跃

第二章:能力与提升

1、零改造迁移实录:2000+存储过程从SQL Server滑入KingbaseES V9R4C12的72小时
2、国产数据库迁移神器,KDMSV4震撼上线

3、在Ubuntu服务器上安装KingbaseES V009R002C012(Orable兼容版)数据库过程详细记录

4、金仓数据库迁移评估系统(KDMS)V4 正式上线:国产化替代的技术底气

5、Ubuntu系统下Python连接国产KingbaseES数据库实现增删改查

6、Java连接电科金仓数据库(KingbaseES)实战指南

Read more

3大开源修复模型横评:云端镜像快速部署,1天完成全面测试

3大开源修复模型横评:云端镜像快速部署,1天完成全面测试 你是不是也遇到过这样的情况:团队要选一个AI图像修复工具,大家各自在本地跑GFPGAN、CodeFormer、GPEN,结果有人用笔记本CPU跑,有人用高端显卡,测试速度、画质效果完全没法比?最后开会讨论时,谁的电脑配置高,谁的结果就“看起来更好”,根本没法做出公正决策。 这正是很多技术主管在搭建AI工具链时最头疼的问题——缺乏统一、可复现的测试环境。不同设备、不同依赖版本、不同参数设置,导致评估结果偏差巨大,选型变成“看运气”。 别急,今天我就来帮你解决这个痛点。我们不靠本地部署“拼电脑”,而是直接上云端标准化镜像环境,一键部署三大主流开源人脸修复模型:GFPGAN、CodeFormer 和 GPEN,在相同GPU资源下完成公平对比测试,1天内搞定从部署到出报告的全流程。 ZEEKLOG星图平台提供了预置好这三大模型的AI镜像,无需手动安装复杂依赖,不用折腾CUDA、PyTorch版本兼容问题,点击即用,还能对外暴露API服务,方便团队成员远程调用测试。整个过程就像租了一台“AI修复工作站”,谁都能用,结果可比对。

By Ne0inhk
手把手教你在GitHub上运行开源项目(新手必看版)

手把手教你在GitHub上运行开源项目(新手必看版)

📦 说在前面 GitHub这个程序员宝藏平台(我愿称之为代码界的金矿),每天都有成千上万的开源项目更新。但是很多新手朋友看到那些酷炫项目时,经常会遇到三大灵魂拷问:这项目怎么跑起来?需要装什么软件?报错了怎么办?今天咱们就用最接地气的方式,手把手教你从0到1运行GitHub项目! 🔧 准备工具包(装机三件套) 1. 代码编辑器(必装) 推荐直接上VS Code这个万金油,装好记得在扩展商店安装这两个插件: * GitLens(代码时光机,能看到每行代码的修改记录) * Code Runner(一键运行脚本的神器) (超级重要)👉 如果项目里有.vscode文件夹,一定要用VS Code打开,里面可能有预置的调试配置! 2. Git客户端(下载代码必备) Windows用户直接装Git for Windows,安装时记得勾选这个选项: Use Git and optional Unix tools from the Command Prompt (这样就能在CMD里用Linux命令了,真香!

By Ne0inhk
弃用MobaXterm,拥抱开源软件Tabby

弃用MobaXterm,拥抱开源软件Tabby

目录 * 引言 * MobaXterm * MobaXterm - Windows下的增强型终端 * 🚀 核心功能点 * 🖥️ X服务器功能 * 💻 终端功能 * 🌐 网络协议支持 * 📁 文件管理功能 * 🔧 高级功能 * 🎨 界面定制 * 📊 会话管理 * 🔌 插件系统 * 🔒 安全功能 * 📱 便携特性 * 🌍 多语言支持 * 📈 专业版增强功能 * 版本说明: * 🔹 家庭版 (Home Edition) * 🔸 专业版 (Professional Edition) * 企业使用建议: * 使用场景: * Tabby * Tabby - 现代化的终端模拟器 * 🚀 核心功能点 * 💻 终端功能 * 🎨 界面定制 * 🔗 网络连接功能 * SSH客户端 * 其他协议 *

By Ne0inhk
第4章:开源模型全景图:如何选择你的技术底座

第4章:开源模型全景图:如何选择你的技术底座

第4章:开源模型全景图:如何选择你的技术底座 引言 开源大模型生态正在经历爆炸式增长。截至2024年6月,HuggingFace平台托管的模型数量已超过50万个,每月新增数千个模型。面对如此庞杂的选择,技术决策者往往陷入两难:是选择规模最大、性能最强的模型,还是选择更符合实际约束的务实方案?本章将建立一套系统的模型选型框架,通过参数规模-性能曲线分析、推理成本量化和许可证风险评估,为技术决策提供科学依据。 1. 开源模型生态现状分析 1.1 主流开源模型系列对比 当前开源大模型生态已形成多个技术流派,各具特色: Llama系列(Meta): * 技术特点:基于Transformer解码器架构,使用RoPE位置编码,采用Grouped-Query Attention优化 * 开源策略:社区友好许可证,允许商业使用(需申请) * 代表型号:Llama-2-7B/13B/70B,Llama-3-8B/70B * 优势:生态完善,工具链成熟,微调资源丰富 Mistral系列: * 技术特点:采用滑动窗口注意力(Sliding Window

By Ne0inhk