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

一、先準備好連接信息
動手之前,先找 DBA 要數(shù)據庫的連接信息。一般會給你一個類似這樣的命令:
./ksql -U system -d test -h 192.168.1.100 -p 54321
這里面包含四個關鍵信息:
- 用戶名:
system(默認管理員) - 數(shù)據庫名:
test - IP 地址:
192.168.1.100 - 端口號:
54321(金倉默認端口)
先用命令行連一下,確認賬號密碼沒問題,再繼續(xù)下一步。
二、項目搭建
2.1 目錄結構
java-kingbase-springdatajpa/
├── pom.xml
├── src/main/
│ ├── java/com/kingbase/testspringdatajpa/
│ │ ├── TestSpringDataJpaApplication.java # 啟動類
│ │ ├── dao/
│ │ │ └── UserRepository.java # 數(shù)據訪問接口
│ │ ├── entity/
│ │ │ └── User.java # 實體類
│ │ └── service/
│ │ ├── UserService.java # 服務接口
│ │ └── impl/UserServiceImpl.java # 服務實現(xiàn)
│ └── resources/
│ └── application.yml # 配置文件
└── src/test/
└── java/.../TestSpringDataJpaApplicationTests.java
和 MyBatis 比,少了一個 IUserMapper.xml,多了一個 service/impl 目錄。JPA 的 Repository 接口自帶基礎 CRUD 方法,不用自己寫實現(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 驅動 -->
<dependency>
<groupId>cn.com.kingbase</groupId>
<artifactId>kingbase8</artifactId>
<version>9.0.0</version>
</dependency>
<!-- Druid 連接池(可選,Spring Boot 默認自帶 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,不用單獨配置。
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 # 自動更新表結構
show-sql: true # 打印 SQL
format-sql: true # 格式化 SQL
open-in-view: false關鍵點:database-platform 必須配成 org.hibernate.dialect.Kingbase8Dialect,Hibernate 才能生成適合金倉的 SQL。
ddl-auto: update 方便開發(fā)測試,生產環(huán)境建議用 none 或 validate。
三、代碼實現(xiàn)
3.1 實體類 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 后,基礎的 save()、findById()、deleteById() 都不用寫,框架自動實現(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);
}
實現(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ù)據庫操作在同一事務中執(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ù)據
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);
}
}
運行結果:
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ù)據刪掉了 id=1,更新了 id=2,分頁正常返回了前 5 條。selectUserByName("insert") 返回 null 因為 id=1 被刪了,剩下的用戶名帶數(shù)字后綴,精確匹配查不到,符合預期。
控制臺還打印了 Hibernate 生成的 SQL,可以清楚地看到框架在背后的工作。
五、JPA 和 MyBatis 怎么選
兩種方式都接入了金倉,順便做個對比:
| 維度 | Spring Data JPA | MyBatis |
|---|---|---|
| 代碼量 | 少(基礎 CRUD 不用寫) | 多(接口 + XML + Service) |
| 靈活性 | 一般 | 高(SQL 完全手寫控制) |
| 復雜查詢 | JPQL 有點繞 | XML 里寫原生 SQL |
| 分頁 | 內置支持,一行代碼 | 需要插件或手寫 |
| 學習成本 | 高(JPA 概念多) | 低(會 SQL 就行) |
| 性能調優(yōu) | Hibernate 生成 SQL 不好控 | SQL 完全掌控 |
建議:單表 CRUD 為主的項目,JPA 能省很多代碼;查詢復雜、需要精細控制 SQL 的,MyBatis 更合適。
順便說一句,金倉對 JPA 的方言支持比較到位,Kingbase8Dialect 能正確處理分頁、序列等特性,用起來基本不用操心方言適配的問題。
六、常見問題
Hibernate 不認識金倉方言:檢查 database-platform 配置是否正確。老版本 Hibernate 可能沒有內置金倉方言,需要升級版本或手動引入方言包。
表名或字段名大小寫問題:實體類中 @Table(name = "test_springdatajpa_2") 保持小寫。如果建表時用了雙引號大小寫敏感,查詢會報“表不存在”。建議統(tǒng)一用小寫,避免麻煩。
ddl-auto: update 不生效:檢查用戶有沒有建表權限。普通用戶可能只有 DML 權限,需要 DBA 授權。
分頁查詢性能問題:JPA 分頁會先執(zhí)行 count 再執(zhí)行 limit,大表場景有性能開銷??梢愿挠?@Query 手寫分頁 SQL 優(yōu)化。
七、寫在最后
從 MySQL 切換到金倉,Spring Data JPA 項目需要改的地方很少:pom.xml 換金倉驅動,application.yml 改數(shù)據庫 URL,dialect 配成金倉專用的。如果代碼里沒用數(shù)據庫特有的方言,基本無縫遷移。
這次體驗下來,我對金倉的生態(tài)兼容性有了更多信心。如果你的項目以單表 CRUD 為主,不妨試試 JPA,同樣能跑得很順。
到此這篇關于Spring Data JPA 接入金倉數(shù)據庫的詳細步驟介紹的文章就介紹到這了,更多相關Spring Data JPA 接入金倉數(shù)據庫內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
在IDEA中配置Selenium和WebDriver的具體操作
在自動化測試領域Selenium是一款非常流行的開源工具,它支持多種瀏覽器,并提供了豐富的API供開發(fā)者使用,而WebDriver則是Selenium的一個重要組件,它負責驅動瀏覽器執(zhí)行測試腳本,這篇文章主要給大家介紹了在IDEA中配置Selenium和WebDriver的具體操作,需要的朋友可以參考下2024-10-10
Mybatis使用XML實現(xiàn)動態(tài)sql的示例代碼
當編寫 MyBatis 中復雜動態(tài) SQL 語句時,使用 XML 格式是一種非常靈活的方式,本文主要為大家詳細介紹了Mybatis使用XML實現(xiàn)動態(tài)sql的具體方法,需要的可以參考下2023-12-12
Spring的BeanUtils.copyProperties屬性復制避坑指南
這篇文章主要介紹了Spring的BeanUtils.copyProperties屬性復制避坑指南,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
java公眾平臺通用接口工具類HttpConnectUtil實例代碼
下面小編就為大家分享一篇java公眾平臺通用接口工具類HttpConnectUtil實例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01

