这是一篇关于 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
<!-- 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 中重新发明一个数据库。