Spring?Data?JPA?接入金倉數(shù)據(jù)庫的詳細(xì)步驟介紹
從一個需求說起
上個月接了個小任務(wù):兩周內(nèi)搭一個用戶中心的原型,要支持增刪改查和分頁。時間緊、活不多,我想著能少寫代碼就少寫。
以前用 MyBatis 的時候,每個表都要手寫 mapper 接口、xml 文件、service 層——一套下來代碼不少。這次想換個思路,試試 Spring Data JPA。之前聽說這玩意兒能在接口里直接寫 SQL,連實(shí)現(xiàn)類都不用,今天正好驗證一下它對金倉數(shù)據(jù)庫的支持怎么樣。
從配依賴到跑通整個 CRUD,大概花了一個多小時。中間還試了自定義 SQL 和分頁,跑得都挺順。今天就把這個過程整理出來。

一、先準(zhǔn)備好連接信息
動手之前,先找 DBA 要數(shù)據(jù)庫的連接信息。一般會給你一個類似這樣的命令:
./ksql -U system -d test -h 192.168.1.100 -p 54321
這里面包含四個關(guān)鍵信息:
- 用戶名:
system(默認(rèn)管理員) - 數(shù)據(jù)庫名:
test - IP 地址:
192.168.1.100 - 端口號:
54321(金倉默認(rèn)端口)
先用命令行連一下,確認(rèn)賬號密碼沒問題,再繼續(xù)下一步。
二、項目搭建
2.1 目錄結(jié)構(gòu)
java-kingbase-springdatajpa/
├── pom.xml
├── src/main/
│ ├── java/com/kingbase/testspringdatajpa/
│ │ ├── TestSpringDataJpaApplication.java # 啟動類
│ │ ├── dao/
│ │ │ └── UserRepository.java # 數(shù)據(jù)訪問接口
│ │ ├── entity/
│ │ │ └── User.java # 實(shí)體類
│ │ └── service/
│ │ ├── UserService.java # 服務(wù)接口
│ │ └── impl/UserServiceImpl.java # 服務(wù)實(shí)現(xiàn)
│ └── resources/
│ └── application.yml # 配置文件
└── src/test/
└── java/.../TestSpringDataJpaApplicationTests.java
和 MyBatis 比,少了一個 IUserMapper.xml,多了一個 service/impl 目錄。JPA 的 Repository 接口自帶基礎(chǔ) CRUD 方法,不用自己寫實(shí)現(xiàn)類。
2.2 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
https://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.0</version>
<relativePath/>
</parent>
<groupId>com.kingbase</groupId>
<artifactId>java-kingbase-springdatajpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- JPA 核心依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Web 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 金倉 JDBC 驅(qū)動 -->
<dependency>
<groupId>cn.com.kingbase</groupId>
<artifactId>kingbase8</artifactId>
<version>9.0.0</version>
</dependency>
<!-- Druid 連接池(可選,Spring Boot 默認(rèn)自帶 HikariCP) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- 測試 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>JPA 的 spring-boot-starter-data-jpa 會自動引入 Hibernate,不用單獨(dú)配置。
2.3 application.yml:配置文件
server:
servlet:
context-path: /testspringdatajpa
port: 8890
spring:
datasource:
driver-class-name: com.kingbase8.Driver
url: jdbc:kingbase8://192.168.1.100:54321/test
username: system
password: 你的密碼
type: com.alibaba.druid.pool.DruidDataSource # 用 Druid 連接池
jpa:
database-platform: org.hibernate.dialect.Kingbase8Dialect
hibernate:
ddl-auto: update # 自動更新表結(jié)構(gòu)
show-sql: true # 打印 SQL
format-sql: true # 格式化 SQL
open-in-view: false關(guān)鍵點(diǎn):database-platform 必須配成 org.hibernate.dialect.Kingbase8Dialect,Hibernate 才能生成適合金倉的 SQL。
ddl-auto: update 方便開發(fā)測試,生產(chǎn)環(huán)境建議用 none 或 validate。
三、代碼實(shí)現(xiàn)
3.1 實(shí)體類 User.java
package com.kingbase.testspringdatajpa.entity;
import javax.persistence.*;
@Entity
@Table(name = "test_springdatajpa_2")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "username")
private String username;
public User() {}
public User(Integer id, String username) {
this.id = id;
this.username = username;
}
// getter / setter 省略...
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
'}';
}
}
@GeneratedValue(strategy = GenerationType.TABLE) 適合老版本金倉。新版可以改用 GenerationType.IDENTITY。
3.2 Repository 接口 UserRepository.java
package com.kingbase.testspringdatajpa.dao;
import com.kingbase.testspringdatajpa.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository("userRepository")
public interface UserRepository extends JpaRepository<User, Integer> {
// 原生 SQL + 位置參數(shù)
@Query(value = "update test_springdatajpa_2 set username = ?1 where id = ?2",
nativeQuery = true)
@Modifying
int updateById(String name, String id);
// JPQL 寫法,參數(shù)命名
@Query("SELECT u FROM User u WHERE u.username = :username")
User findUser(@Param("username") String username);
}
繼承 JpaRepository 后,基礎(chǔ)的 save()、findById()、deleteById() 都不用寫,框架自動實(shí)現(xiàn)。
3.3 Service 層
接口 UserService.java:
package com.kingbase.testspringdatajpa.service;
import com.kingbase.testspringdatajpa.entity.User;
import java.util.Iterator;
public interface UserService {
void insertUser(User user);
void deleteUser(Integer id);
int updateUser(User user);
int updateUserById(String name, String id);
User selectUserById(Integer id);
User selectUserByName(String username);
Iterator<User> selectUserAll(Integer pageNum, Integer pageSize);
}
實(shí)現(xiàn)類 UserServiceImpl.java:
package com.kingbase.testspringdatajpa.service.impl;
import com.kingbase.testspringdatajpa.dao.UserRepository;
import com.kingbase.testspringdatajpa.entity.User;
import com.kingbase.testspringdatajpa.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Iterator;
import java.util.Optional;
@Service
@Transactional
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
@Autowired
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public void insertUser(User user) {
userRepository.save(user);
}
@Override
public void deleteUser(Integer id) {
if (!userRepository.existsById(id)) {
return;
}
userRepository.deleteById(id);
}
@Override
public int updateUser(User user) {
userRepository.save(user);
return 1;
}
@Override
public int updateUserById(String name, String id) {
return userRepository.updateById(name, id);
}
@Override
public User selectUserById(Integer id) {
Optional<User> optional = userRepository.findById(id);
return optional.orElse(null);
}
@Override
public User selectUserByName(String username) {
return userRepository.findUser(username);
}
@Override
public Iterator<User> selectUserAll(Integer pageNum, Integer pageSize) {
Sort sort = Sort.by(Sort.Direction.ASC, "id");
Pageable pageable = PageRequest.of(pageNum, pageSize, sort);
Page<User> users = userRepository.findAll(pageable);
return users.iterator();
}
}
@Transactional 確保數(shù)據(jù)庫操作在同一事務(wù)中執(zhí)行。
3.4 啟動類
package com.kingbase.testspringdatajpa;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TestSpringDataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(TestSpringDataJpaApplication.class, args);
}
}
四、測試驗證
package com.kingbase.testspringdatajpa;
import com.kingbase.testspringdatajpa.entity.User;
import com.kingbase.testspringdatajpa.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Iterator;
@SpringBootTest
public class TestSpringDataJpaApplicationTests {
@Autowired
private UserService userService;
@Test
public void contextLoads() {
// 1. 插入 10 條數(shù)據(jù)
for (int i = 1; i <= 10; i++) {
userService.insertUser(new User(i, "insert" + i));
}
// 2. 刪除 id=1
userService.deleteUser(1);
// 3. 更新 id=2,改名為 update
userService.updateUser(new User(2, "update"));
// 4. 按 ID 查詢
User user = userService.selectUserById(2);
System.out.println("user = " + user);
// 5. 按用戶名查詢
User userByName = userService.selectUserByName("insert");
System.out.println("userByName = " + userByName);
// 6. 分頁查詢(第 1 頁,每頁 5 條)
Iterator<User> userIterator = userService.selectUserAll(0, 5);
userIterator.forEachRemaining(System.out::println);
}
}
運(yùn)行結(jié)果:
user = User{id=2, username='update'}
userByName = null
User{id=1, username='insert1'}
User{id=2, username='update'}
User{id=3, username='insert3'}
User{id=4, username='insert4'}
User{id=5, username='insert5'}
數(shù)據(jù)刪掉了 id=1,更新了 id=2,分頁正常返回了前 5 條。selectUserByName("insert") 返回 null 因為 id=1 被刪了,剩下的用戶名帶數(shù)字后綴,精確匹配查不到,符合預(yù)期。
控制臺還打印了 Hibernate 生成的 SQL,可以清楚地看到框架在背后的工作。
五、JPA 和 MyBatis 怎么選
兩種方式都接入了金倉,順便做個對比:
| 維度 | Spring Data JPA | MyBatis |
|---|---|---|
| 代碼量 | 少(基礎(chǔ) CRUD 不用寫) | 多(接口 + XML + Service) |
| 靈活性 | 一般 | 高(SQL 完全手寫控制) |
| 復(fù)雜查詢 | JPQL 有點(diǎn)繞 | XML 里寫原生 SQL |
| 分頁 | 內(nèi)置支持,一行代碼 | 需要插件或手寫 |
| 學(xué)習(xí)成本 | 高(JPA 概念多) | 低(會 SQL 就行) |
| 性能調(diào)優(yōu) | Hibernate 生成 SQL 不好控 | SQL 完全掌控 |
建議:單表 CRUD 為主的項目,JPA 能省很多代碼;查詢復(fù)雜、需要精細(xì)控制 SQL 的,MyBatis 更合適。
順便說一句,金倉對 JPA 的方言支持比較到位,Kingbase8Dialect 能正確處理分頁、序列等特性,用起來基本不用操心方言適配的問題。
六、常見問題
Hibernate 不認(rèn)識金倉方言:檢查 database-platform 配置是否正確。老版本 Hibernate 可能沒有內(nèi)置金倉方言,需要升級版本或手動引入方言包。
表名或字段名大小寫問題:實(shí)體類中 @Table(name = "test_springdatajpa_2") 保持小寫。如果建表時用了雙引號大小寫敏感,查詢會報“表不存在”。建議統(tǒng)一用小寫,避免麻煩。
ddl-auto: update 不生效:檢查用戶有沒有建表權(quán)限。普通用戶可能只有 DML 權(quán)限,需要 DBA 授權(quán)。
分頁查詢性能問題:JPA 分頁會先執(zhí)行 count 再執(zhí)行 limit,大表場景有性能開銷??梢愿挠?@Query 手寫分頁 SQL 優(yōu)化。
七、寫在最后
從 MySQL 切換到金倉,Spring Data JPA 項目需要改的地方很少:pom.xml 換金倉驅(qū)動,application.yml 改數(shù)據(jù)庫 URL,dialect 配成金倉專用的。如果代碼里沒用數(shù)據(jù)庫特有的方言,基本無縫遷移。
這次體驗下來,我對金倉的生態(tài)兼容性有了更多信心。如果你的項目以單表 CRUD 為主,不妨試試 JPA,同樣能跑得很順。
到此這篇關(guān)于Spring Data JPA 接入金倉數(shù)據(jù)庫的詳細(xì)步驟介紹的文章就介紹到這了,更多相關(guān)Spring Data JPA 接入金倉數(shù)據(jù)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在IDEA中配置Selenium和WebDriver的具體操作
在自動化測試領(lǐng)域Selenium是一款非常流行的開源工具,它支持多種瀏覽器,并提供了豐富的API供開發(fā)者使用,而WebDriver則是Selenium的一個重要組件,它負(fù)責(zé)驅(qū)動瀏覽器執(zhí)行測試腳本,這篇文章主要給大家介紹了在IDEA中配置Selenium和WebDriver的具體操作,需要的朋友可以參考下2024-10-10
一鍵部署SpringCloud 微服務(wù)的詳細(xì)流程
本文詳解通過Jenkins、K8s、Docker實(shí)現(xiàn)SpringCloud微服務(wù)自動化部署流程,涵蓋SSH密鑰配置、代碼拉取構(gòu)建、鏡像打包推送及K8s資源發(fā)布,感興趣的朋友跟隨小編一起看看吧2025-10-10
基于Java回顧之網(wǎng)絡(luò)通信的應(yīng)用分析
在這篇文章里,我們主要討論如何使用Java實(shí)現(xiàn)網(wǎng)絡(luò)通信,包括TCP通信、UDP通信、多播以及NIO2013-05-05
基于java實(shí)現(xiàn)簡單的銀行管理系統(tǒng)
這篇文章主要介紹了基于java實(shí)現(xiàn)簡單的銀行管理系統(tǒng),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
Mybatis使用XML實(shí)現(xiàn)動態(tài)sql的示例代碼
當(dāng)編寫 MyBatis 中復(fù)雜動態(tài) SQL 語句時,使用 XML 格式是一種非常靈活的方式,本文主要為大家詳細(xì)介紹了Mybatis使用XML實(shí)現(xiàn)動態(tài)sql的具體方法,需要的可以參考下2023-12-12
SpringBoot進(jìn)行多表查詢功能的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot進(jìn)行多表查詢功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09
Spring的BeanUtils.copyProperties屬性復(fù)制避坑指南
這篇文章主要介紹了Spring的BeanUtils.copyProperties屬性復(fù)制避坑指南,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
java公眾平臺通用接口工具類HttpConnectUtil實(shí)例代碼
下面小編就為大家分享一篇java公眾平臺通用接口工具類HttpConnectUtil實(shí)例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01

