【Kotlin + Spring Boot 4 从零到架构师】第 17 篇:PostgreSQL + Docker 环境搭建

本系列定位:零基础入门,从 Kotlin 语法一路到 Spring Boot 4 高级架构(DDD + Modulith),适合 Java 开发者转型,也适合纯新手系统学习。


本篇你将学到

  • 用 Docker 快速部署 PostgreSQL 16
  • Spring Boot 连接 PostgreSQL 的配置
  • HikariCP 连接池的概念与关键参数
  • 验证数据库连通性

学完本篇,mini-shop 将从内存存储升级为真正的数据库持久化。


一、安装 Docker

1.1 为什么用 Docker 部署数据库

  • 一键部署:不需要在系统上手动安装 PostgreSQL
  • 环境隔离:不同项目可以用不同版本的数据库,互不干扰
  • 与生产一致:开发环境与生产环境使用相同的 Docker 镜像
  • 便于清理:不想要了直接删容器,不污染系统

1.2 安装 Docker

Windows / macOS
  1. 访问 Docker Desktop 官网
  2. 下载并安装对应平台的版本
  3. 启动 Docker Desktop,等待右下角图标变为绿色
Linux(Debian/Ubuntu)
# 官方一键安装脚本
curl -fsSL https://get.docker.com | sh

# 启动 Docker 服务
sudo systemctl start docker
sudo systemctl enable docker

# 验证
docker --version

验证安装成功:终端执行 docker --version,看到版本号即可。


下面是 Docker 部署 PostgreSQL 的整体流程:

running

stopped

安装 Docker

创建 docker-compose.yml

docker compose up -d

容器状态检查

验证连接

查看日志排查

Spring Boot 连接配置

二、部署 PostgreSQL

2.1 docker-compose 方式(推荐)

在 mini-shop 项目根目录创建 docker-compose.yml

version: "3.9"

services:
  postgres:
    image: postgres:16-alpine
    container_name: mini-shop-postgres
    environment:
      POSTGRES_DB: mini_shop
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres123
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  postgres_data:
配置项说明
image: postgres:16-alpinePostgreSQL 16 的 Alpine 精简版镜像(体积小)
POSTGRES_DB自动创建的数据库名
POSTGRES_USER / POSTGRES_PASSWORD用户名和密码
ports: "5432:5432"宿主机端口 → 容器端口映射
volumes: postgres_data数据持久化——容器删除后数据不丢失

2.2 启动数据库

# 在项目根目录执行
docker compose up -d

# -d 表示后台运行

验证容器状态:

docker compose ps

看到 mini-shop-postgres 状态为 running 即可。

2.3 验证数据库连接

# 进入 PostgreSQL 交互终端
docker exec -it mini-shop-postgres psql -U postgres -d mini_shop

# 执行 SQL
\l               # 列出所有数据库
\dt              # 列出表(目前为空)
\q               # 退出

2.4 常用 Docker 命令

# 停止数据库
docker compose stop

# 启动(已创建的容器)
docker compose start

# 停止并删除容器(数据保留在 volume 中)
docker compose down

# 停止并删除容器 + 删除数据(完全重置)
docker compose down -v

# 查看数据库日志
docker compose logs postgres

三、Spring Boot 连接配置

3.1 添加依赖

确保 build.gradle.kts 中有 JPA 和 PostgreSQL 依赖:

dependencies {
    // Spring Data JPA(包含 Hibernate 7)
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")

    // PostgreSQL 驱动
    runtimeOnly("org.postgresql:postgresql")

    // 之前的依赖...
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-validation")
}

3.2 配置数据源

修改 application-dev.yml

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mini_shop
    username: postgres
    password: postgres123
    driver-class-name: org.postgresql.Driver

  jpa:
    # 自动根据实体类生成/更新表结构(开发环境用,生产环境关闭!)
    hibernate:
      ddl-auto: update

    # 在控制台打印 SQL 语句(开发环境调试用)
    show-sql: true

    properties:
      hibernate:
        # 格式化 SQL 输出
        format_sql: true
        # 指定数据库方言
        dialect: org.hibernate.dialect.PostgreSQLDialect

3.3 ddl-auto 各值说明

行为适用环境
none不做任何操作生产
validate只验证实体与表结构是否匹配,不修改生产
update根据实体自动更新表结构(新增列/表)开发
create每次启动删除并重建所有表测试(会丢数据!)
create-drop启动时创建,退出时删除测试

重要警告ddl-auto: update 仅限开发环境!生产环境必须用 validatenone,通过 Liquibase(第 22 篇)管理表结构变更。

3.4 JPA 与 Hibernate 的关系

JPA(Jakarta Persistence API)
  ← 标准规范(接口),定义了 ORM 的标准 API
  
Hibernate
  ← JPA 的实现之一(最流行的实现)
  
Spring Data JPA
  ← 在 JPA 之上再加一层封装(Repository 接口自动实现)

层级关系:Spring Data JPA → JPA(接口)→ Hibernate(实现)→ 数据库


下面是 JPA 与 Hibernate 的层级关系图:

数据层

实现层

规范层

应用层

调用

标准接口

JDBC 驱动

Spring Data JPA
Repository 接口

JPA
Jakarta Persistence API

Hibernate 7
ORM 框架

PostgreSQL 数据库

四、HikariCP 连接池

4.1 为什么需要连接池

每次数据库操作都创建/销毁 TCP 连接开销很大。连接池预先创建一批连接并复用:

没有连接池:每次请求 → 创建连接 → 执行 SQL → 销毁连接(慢)
有连接池:  每次请求 → 从池中借连接 → 执行 SQL → 归还到池中(快)

4.2 Spring Boot 默认连接池

Spring Boot 默认使用 HikariCP——目前性能最好的 JDBC 连接池,不需要额外配置。

4.3 关键参数调优

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mini_shop
    username: postgres
    password: postgres123
    hikari:
      # 最大连接数(默认 10,生产环境建议 = CPU 核心数 * 2 + 磁盘数)
      maximum-pool-size: 10
      # 最小空闲连接数(默认 = maximum-pool-size)
      minimum-idle: 5
      # 连接超时时间(默认 30 秒)
      connection-timeout: 30000
      # 连接最长存活时间(默认 30 分钟)
      max-lifetime: 1800000
      # 空闲连接超时(默认 10 分钟)
      idle-timeout: 600000
      # 连接池名称
      pool-name: MiniShopHikariPool

入门建议:开发阶段用默认配置即可。生产调优在模块八(性能调优)中详细讲解。


下面是连接池工作原理的对比图:

有连接池(HikariCP)

请求到达

从池中借连接

执行 SQL

归还到池中

响应返回

没有连接池

请求到达

创建 TCP 连接

执行 SQL

销毁连接

响应返回

五、连接验证

5.1 启动项目验证

确保 Docker 中 PostgreSQL 已启动,然后运行 Spring Boot 项目。

控制台看到类似日志说明连接成功:

HikariPool-1 - Starting...
HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@...
HikariPool-1 - Start completed.

5.2 常见连接问题排查

问题一:Connection refused
Connection refused: localhost/127.0.0.1:5432

原因:PostgreSQL 容器没有启动。

# 检查容器状态
docker compose ps

# 如果没有运行,启动它
docker compose up -d
问题二:Authentication failed
FATAL: password authentication failed for user "postgres"

原因:密码不匹配。检查 application-dev.yml 中的密码与 docker-compose.yml 中的 POSTGRES_PASSWORD 是否一致。

如果修改了 docker-compose.yml 中的密码,需要先 docker compose down -v(删除旧数据卷)再重新 docker compose up -d

问题三:Database does not exist
FATAL: database "mini_shop" does not exist

原因:数据库名不匹配。检查 URL 中的数据库名与 POSTGRES_DB 是否一致。


下面是连接问题排查流程图:

连接失败

Connection refused?

检查容器是否运行
docker compose ps

未运行则启动
docker compose up -d

Authentication failed?

检查密码是否一致
application-dev.yml ↔ docker-compose.yml

修改密码后
docker compose down -v 再重启

Database does not exist?

检查数据库名是否一致
URL 中的库名 ↔ POSTGRES_DB

查看完整日志
docker compose logs postgres

连接成功 ✅

六、小结与项目结构

本篇完成后,mini-shop 项目结构:

mini-shop/
├── docker-compose.yml           ← PostgreSQL 容器配置
├── build.gradle.kts
├── src/main/
│   ├── kotlin/com/example/minishop/
│   │   ├── MiniShopApplication.kt
│   │   ├── controller/
│   │   ├── service/
│   │   ├── repository/
│   │   ├── dto/
│   │   └── config/
│   └── resources/
│       ├── application.yml
│       └── application-dev.yml  ← 数据库连接配置

本篇小结

知识点核心内容
Docker 部署 PostgreSQLdocker compose up -d 一键启动
数据持久化Docker Volume 保证容器删除后数据不丢
连接配置spring.datasource 配置 URL/用户名/密码
ddl-autoupdate(开发)/ validate(生产)
HikariCPSpring Boot 默认连接池,高性能
JPA → Hibernate规范 → 实现的关系
连接池原理预创建连接复用,避免频繁创建/销毁

下篇预告

第 18 篇:Hibernate 7 与 JPA — 实体映射基础

如何把 Kotlin 类映射为数据库表?@Entity / @Table / @Id / @Column 各自的作用?下一篇将 mini-shop 的商品模型映射到 PostgreSQL。


如果本篇内容对你有帮助,欢迎点赞收藏!有任何疑问,欢迎在评论区交流。

更多推荐