跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Spring Boot 数据访问与数据库集成实战

深入解析 Spring Boot 数据访问与数据库集成方案。涵盖 MySQL 与 H2 的配置差异、JPA 与 MyBatis 的技术选型对比、事务管理机制及实际代码落地。重点讲解如何通过自动配置简化数据源接入,利用 Repository 接口减少样板代码,并结合真实场景演示商品管理系统的完整实现流程,帮助开发者掌握高效、安全的数据持久化实践。

月亮邮递员发布于 2026/3/25更新于 2026/10/26105 浏览
Spring Boot 数据访问与数据库集成实战

Spring Boot 数据访问与数据库集成

Spring Boot 数据访问架构示意

概述

在 Spring Boot 应用中,数据访问是核心环节。它不仅仅是简单的增删改查,更涉及事务管理、持久化策略以及不同 ORM 框架的选型。Spring Boot 通过自动配置极大地简化了这些流程,让开发者能专注于业务逻辑。

常用的数据访问组件包括:

  • JdbcTemplate:适合需要精细控制 JDBC 操作的场景。
  • JPA (Hibernate):对象关系映射的标准实现,开发效率高。
  • MyBatis:灵活性强,SQL 可控性高。

集成 MySQL

MySQL 是最流行的开源数据库之一,Spring Boot 与其集成非常成熟。

依赖配置

首先在 pom.xml 中引入 Web、Data JPA 和 MySQL 驱动依赖。注意驱动作用域设为 runtime,避免打包进生产环境时冗余。

<dependencies>
    <!-- Web 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Data JPA 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- MySQL 驱动 -->
    <dependency>
        <>mysql
        mysql-connector-java
        runtime
    
    
    
        org.springframework.boot
        spring-boot-starter-test
        test
    

groupId
</groupId>
<artifactId>
</artifactId>
<scope>
</scope>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>
</groupId>
<artifactId>
</artifactId>
<scope>
</scope>
</dependency>
</dependencies>

连接配置

在 application.properties 中配置数据源。这里建议开启 SQL 打印以便调试,并设置 Hibernate 自动更新表结构(开发环境慎用)。

server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

实体与仓库

定义一个 Product 实体类,使用 JPA 注解映射数据库表。记得处理好 Getter/Setter 方法,这是 JavaBean 规范的基础。

import javax.persistence.*;

@Entity
@Table(name = "product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String productId;
    private String productName;
    private double price;
    private int sales;

    public Product() {}

    public Product(String productId, String productName, double price, int sales) {
        this.productId = productId;
        this.productName = productName;
        this.price = price;
        this.sales = sales;
    }

    // Getter 和 Setter 方法省略,实际开发中建议使用 Lombok 简化
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getProductId() { return productId; }
    public void setProductId(String productId) { this.productId = productId; }
    public String getProductName() { return productName; }
    public void setProductName(String productName) { this.productName = productName; }
    public double getPrice() { return price; }
    public void setPrice(double price) { this.price = price; }
    public int getSales() { return sales; }
    public void setSales(int sales) { this.sales = sales; }
}

接着创建 Repository 接口继承 JpaRepository,无需编写实现类即可拥有基础 CRUD 能力。如果需要自定义查询,可以直接在接口方法名中约定规则。

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findBySalesGreaterThan(int sales);
}

控制器层

最后编写 RESTful 风格的 Controller,注入 Repository 进行调用。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/api/products")
public class ProductController {
    @Autowired
    private ProductRepository productRepository;

    @GetMapping("/")
    public List<Product> getAllProducts() {
        return productRepository.findAll();
    }

    @PostMapping("/")
    public Product addProduct(@RequestBody Product product) {
        return productRepository.save(product);
    }

    @GetMapping("/top-selling")
    public List<Product> getTopSellingProducts(@RequestParam int topN) {
        List<Product> products = productRepository.findBySalesGreaterThan(0);
        products.sort((p1, p2) -> p2.getSales() - p1.getSales());
        if (products.size() > topN) {
            return products.subList(0, topN);
        }
        return products;
    }
}

集成 H2 内存数据库

H2 数据库非常适合开发和测试阶段,因为它基于内存运行,启动快且无需额外安装。

配置差异

主要区别在于 pom.xml 中的依赖和 application.properties 中的 URL。

<!-- H2 数据库依赖 -->
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
# 开启 H2 控制台方便查看数据
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

实体类和 Repository 的定义与 MySQL 方案基本一致,这使得切换数据库变得非常容易。

集成 MyBatis

如果你更喜欢手写 SQL 或者需要更复杂的动态 SQL,MyBatis 是更好的选择。

依赖与配置

引入 MyBatis Starter 和 MySQL 驱动。

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.3.0</version>
</dependency>

配置文件需指定 Mapper XML 的位置和别名包。

mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.example.demo.entity

Mapper 接口与 XML

MyBatis 采用接口 + XML 的方式。接口定义方法签名,XML 文件编写具体 SQL。

import org.apache.ibatis.annotations.Mapper;
import java.util.List;

@Mapper
public interface ProductMapper {
    List<Product> findAll();
    int insert(Product product);
    List<Product> findBySalesGreaterThan(int sales);
}
<?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.demo.mapper.ProductMapper">
    <resultMap id="ProductResultMap" type="com.example.demo.entity.Product">
        <id property="id" column="id"/>
        <result property="productId" column="product_id"/>
        <result property="productName" column="product_name"/>
        <result property="price" column="price"/>
        <result property="sales" column="sales"/>
    </resultMap>
    <select id="findAll" resultMap="ProductResultMap"> SELECT * FROM product </select>
    <insert id="insert" parameterType="com.example.demo.entity.Product">
        INSERT INTO product (product_id, product_name, price, sales) VALUES (#{productId}, #{productName}, #{price}, #{sales})
    </insert>
    <select id="findBySalesGreaterThan" parameterType="int" resultMap="ProductResultMap">
        SELECT * FROM product WHERE sales > #{sales}
    </select>
</mapper>

事务管理

在数据访问层,事务一致性至关重要。Spring Boot 提供了声明式事务支持,只需添加 @Transactional 注解。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;

    @Transactional
    public void addProduct(Product product) {
        productRepository.save(product);
    }

    @Transactional(readOnly = true)
    public List<Product> getAllProducts() {
        return productRepository.findAll();
    }
}

注意:readOnly = true 可以优化只读查询的性能。另外,事务通常应用在 Service 层,而不是 Controller 或 Repository 层,这样更符合分层架构的最佳实践。

实际应用场景

在实际项目中,我们通常会组合上述技术栈。例如构建一个商品管理系统,包含展示、购买、订单管理等模块。

下面是一个整合后的完整示例,展示了从启动类到测试类的完整链路。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.persistence.*;
import java.util.List;

@SpringBootApplication
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }

    @Autowired
    private ProductService productService;

    public void run(String... args) {
        productService.addProduct(new Product("P001", "手机", 1000.0, 100));
        productService.addProduct(new Product("P002", "电脑", 5000.0, 50));
        productService.addProduct(new Product("P003", "电视", 3000.0, 80));
        productService.addProduct(new Product("P004", "手表", 500.0, 200));
        productService.addProduct(new Product("P005", "耳机", 300.0, 150));
    }
}

@Entity
@Table(name = "product")
class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String productId;
    private String productName;
    private double price;
    private int sales;

    public Product() {}

    public Product(String productId, String productName, double price, int sales) {
        this.productId = productId;
        this.productName = productName;
        this.price = price;
        this.sales = sales;
    }

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getProductId() { return productId; }
    public void setProductId(String productId) { this.productId = productId; }
    public String getProductName() { return productName; }
    public void setProductName(String productName) { this.productName = productName; }
    public double getPrice() { return price; }
    public void setPrice(double price) { this.price = price; }
    public int getSales() { return sales; }
    public void setSales(int sales) { this.sales = sales; }
}

@Repository
interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findBySalesGreaterThan(int sales);
}

@Service
class ProductService {
    @Autowired
    private ProductRepository productRepository;

    @Transactional
    public void addProduct(Product product) {
        productRepository.save(product);
    }

    @Transactional(readOnly = true)
    public List<Product> getAllProducts() {
        return productRepository.findAll();
    }

    @Transactional(readOnly = true)
    public List<Product> getTopSellingProducts(int topN) {
        List<Product> products = productRepository.findBySalesGreaterThan(0);
        products.sort((p1, p2) -> p2.getSales() - p1.getSales());
        if (products.size() > topN) {
            return products.subList(0, topN);
        }
        return products;
    }
}

@RestController
@RequestMapping("/api/products")
class ProductController {
    @Autowired
    private ProductService productService;

    @GetMapping("/")
    public List<Product> getAllProducts() {
        return productService.getAllProducts();
    }

    @PostMapping("/")
    public void addProduct(@RequestBody Product product) {
        productService.addProduct(product);
    }

    @PutMapping("/{id}")
    public void updateProduct(@PathVariable Long id, @RequestBody Product product) {
        product.setId(id);
        productService.updateProduct(product);
    }

    @DeleteMapping("/{id}")
    public void deleteProduct(@PathVariable Long id) {
        productService.deleteProduct(id);
    }

    @GetMapping("/top-selling")
    public List<Product> getTopSellingProducts(@RequestParam int topN) {
        return productService.getTopSellingProducts(topN);
    }
}

运行后访问 /api/products/top-selling?topN=3,你将看到销量最高的前三件商品返回 JSON 数据。这种端到端的集成方式,能够让你快速验证业务逻辑。

结语

本章涵盖了 Spring Boot 数据访问的核心内容。无论是轻量级的 JdbcTemplate,还是强大的 JPA 或灵活的 MyBatis,Spring Boot 都能提供开箱即用的支持。事务管理则是保障数据安全的最后一道防线。在实际开发中,根据项目复杂度选择合适的方案,配合良好的分层设计,才能构建出稳健的数据访问层。

目录

  1. Spring Boot 数据访问与数据库集成
  2. 概述
  3. 集成 MySQL
  4. 依赖配置
  5. 连接配置
  6. 实体与仓库
  7. 控制器层
  8. 集成 H2 内存数据库
  9. 配置差异
  10. 开启 H2 控制台方便查看数据
  11. 集成 MyBatis
  12. 依赖与配置
  13. Mapper 接口与 XML
  14. 事务管理
  15. 实际应用场景
  16. 结语

更多推荐文章

查看全部
  • C++ 哈希表模拟实现:闭散列与冲突处理
  • 缓存算法实战:LRU 与 LFU 原理及 Java 实现
  • 次模函数(Submodular Function)核心概念与机器学习应用
  • Flutter 三方库 web_ffi 的鸿蒙化适配指南
  • 使用 Docker 部署 Apache Answer 并通过 cpolar 实现公网访问
  • 基于 Java 的大数据实时流处理在工业物联网设备状态监测中的应用与挑战
  • 学习大语言模型原理必看的 10 篇论文
  • GPT Image 2 安全审查真相:不是只看“性感”,而是在预测你的意图
  • 【AI审稿提示词】—— 严肃的审稿人
  • 基于 Java + MyBatis + MySQL 的 Web 时间日程管理系统
  • Python 列表与元组的区别及常用操作
  • Cookie 机制深度解析:原理、版本与局限
  • OpenClaw 推出图形界面版 ClawX,简化 AI 智能体编排配置
  • 二叉树 DFS 实战:计算布尔值与路径数字和
  • 完备低代码平台的架构全景与核心能力
  • Python 爬虫开发实战:从 Requests 到分布式部署
  • Python 3.14 在 Windows 上的安装指南
  • 利用 AI 工具自动生成高质量 Python 爬虫代码
  • 万方AIGC检测降重工具实测与选择指南
  • Whisper-large-v3 在线语音转文字零代码实践

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online