Spring Boot 整合 Spring Data JDBC:从零开始搭建高性能应用 – wiki基地

这是一篇关于 Spring Boot 整合 Spring Data JDBC 的详细技术文章草稿。


Spring Boot 整合 Spring Data JDBC:从零开始搭建高性能应用

在 Java 领域,ORM(对象关系映射)框架如 Hibernate/JPA 长期占据主导地位。然而,随着微服务架构和领域驱动设计(DDD)的兴起,开发者开始追求更轻量、更可控的数据访问层。Spring Data JDBC 应运而生,它移除了 JPA 的复杂缓存和延迟加载机制,提供了一种“纯粹”且高性能的 SQL 映射方案。

本文将带你从零开始,搭建一个基于 Spring Boot 和 Spring Data JDBC 的高性能应用。

1. 为什么选择 Spring Data JDBC?

与 Spring Data JPA 相比,Spring Data JDBC 的设计哲学完全不同:
* 没有由框架管理的缓存(First/Second Level Cache):你的查询直接对应数据库操作,没有副作用。
* 没有延迟加载(Lazy Loading):避免了经典的 “N+1” 查询陷阱,模型加载即完整。
* 领域驱动设计(DDD)友好:强制以“聚合根(Aggregate Root)”为单位进行操作,简化了复杂对象图的管理。
* 高性能:底层直接基于 JDBC,开销极小,启动速度快。

2. 环境搭建

首先,我们需要创建一个 Spring Boot 项目。你可以使用 Spring Initializr

依赖配置 (pom.xml):

你需要引入 spring-boot-starter-data-jdbc 和数据库驱动(这里以 MySQL 为例)。

“`xml



org.springframework.boot
spring-boot-starter-data-jdbc

<!-- Web (用于测试 API) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- MySQL Driver -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- Lombok (可选,简化代码) -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>


“`

3. 数据库配置

src/main/resources/application.yml 中配置数据源。Spring Data JDBC 默认使用 Spring Boot 的 DataSource

yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo_db?useSSL=false&serverTimezone=UTC
username: root
password: yourpassword
driver-class-name: com.mysql.cj.jdbc.Driver
sql:
init:
mode: always # 启动时初始化 schema(可选)

你需要手动创建表结构,因为 Spring Data JDBC 不会自动生成 DDL(这符合其“简单可控”的原则)。

sql
CREATE TABLE IF NOT EXISTS user_account (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100),
balance DECIMAL(10, 2)
);

4. 构建领域模型 (Entity)

Spring Data JDBC 的实体类非常纯粹。核心注解是 @Id@Table

注意:Spring Data JDBC 强烈建议使用不可变对象(Immutable Objects),可以通过构造函数映射。

“`java
package com.example.demo.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.With; // 这是一个非常棒的 Lombok 注解,用于创建修改后的副本

import java.math.BigDecimal;

@Data
@AllArgsConstructor
@Table(“user_account”) // 显式指定表名
public class UserAccount {

@Id // 必须标记主键
private Long id;

private String username;
private String email;
private BigDecimal balance;

// 也可以使用静态工厂方法或 Builder
public static UserAccount create(String username, String email) {
    return new UserAccount(null, username, email, BigDecimal.ZERO);
}

}
“`

5. 编写 Repository

继承 ListCrudRepository (Spring Data 3.x) 或 CrudRepository

“`java
package com.example.demo.repository;

import com.example.demo.entity.UserAccount;
import org.springframework.data.jdbc.repository.query.Modifying;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.ListCrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.List;

@Repository
public interface UserAccountRepository extends ListCrudRepository {

// 1. 基于方法名的自动生成查询
List<UserAccount> findByUsername(String username);

// 2. 自定义 SQL 查询 (直接写 SQL,完全掌控性能)
@Query("SELECT * FROM user_account WHERE balance > :minBalance")
List<UserAccount> findRichUsers(@Param("minBalance") BigDecimal minBalance);

// 3. 修改操作
@Modifying
@Query("UPDATE user_account SET balance = balance + :amount WHERE id = :id")
int deposit(@Param("id") Long id, @Param("amount") BigDecimal amount);

}
“`

6. 服务层与事务

Spring Data JDBC 使用标准的 Spring @Transactional 进行事务管理。

“`java
package com.example.demo.service;

import com.example.demo.entity.UserAccount;
import com.example.demo.repository.UserAccountRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Service
public class UserService {

private final UserAccountRepository repository;

public UserService(UserAccountRepository repository) {
    this.repository = repository;
}

@Transactional
public UserAccount createUser(String username, String email) {
    UserAccount account = UserAccount.create(username, email);
    // 保存时,如果 id 为 null,Spring Data JDBC 会视为 INSERT
    // 保存后,返回的对象会包含数据库生成的 ID
    return repository.save(account);
}

@Transactional(readOnly = true)
public Iterable<UserAccount> getAllUsers() {
    return repository.findAll();
}

}
“`

7. 高级特性:聚合与 1:N 关系

这是 Spring Data JDBC 最精髓的部分。在 DDD 中,通过聚合根来访问数据。如果你有一个 Order (订单) 和 OrderItem (订单项),Order 就是聚合根。

当你保存 Order 时,Spring Data JDBC 会自动保存、更新或删除 OrderItem

“`java
@Table(“orders”)
public class Order {
@Id
private Long id;

// 1:N 关系,直接映射为 Set 或 List
// 这里的 OrderItem 不需要是完整的 Entity,不需要 Repository
@MappedCollection(idColumn = "order_id") 
private Set<OrderItem> items;

public void addItem(OrderItem item) {
    this.items.add(item);
}

}

@Table(“order_items”)
public class OrderItem {
// 通常不需要独立的 @Id,或者仅用于内部区分
private String productName;
private int quantity;
}
“`

当你调用 orderRepository.save(order) 时,框架会自动处理 orders 表和 order_items 表的数据同步(先删后插或智能更新),确保聚合的一致性。

8. 总结

Spring Data JDBC 是构建高性能、易维护 Spring Boot 应用的理想选择,特别是当你:
1. 厌倦了 JPA 的复杂状态管理
2. 喜欢直接掌控 SQL
3. 实践领域驱动设计 (DDD)
4. 需要极快的启动速度低内存占用(适合 Serverless 或 Native Image)。

它让数据库回归了存储的本质,而不是试图在 Java 中重新发明一个数据库。

滚动至顶部