PostgreSQL 入门与实践:从零搭建一个 CRUD 应用

PostgreSQL 入门与实践:从零搭建一个 CRUD 应用

一、PostgreSQL 简介

PostgreSQL 是一个功能强大的开源对象关系型数据库系统,拥有超过 30 年的活跃开发历史。它以其可靠性、功能丰富性和对 SQL 标准的高度兼容性而闻名。

核心特性

  • 开源免费:PostgreSQL 采用 PostgreSQL 许可证,类似于 MIT 或 BSD,可以自由使用、修改和分发。
  • ACID 事务:完全支持原子性、一致性、隔离性和持久性,确保数据安全可靠。
  • 丰富的数据类型:除了标准类型,还支持 JSON/JSONB、数组、hstore(键值存储)、UUID、几何类型等。
  • 扩展性:支持自定义函数、操作符、数据类型和索引方法。流行的扩展如 PostGIS(地理空间)和 pgvector(向量搜索)使其应用场景远超传统数据库。
  • 并发控制:使用 MVCC(多版本并发控制)实现高并发读写,读不阻塞写,写不阻塞读。
  • 高级索引:支持 B-tree、Hash、GiST、GIN、BRIN 等多种索引类型。
  • 视图、触发器、存储过程:支持用多种语言(PL/pgSQL、PL/Python、PL/Perl 等)编写函数和触发器。

与其他数据库的比较

特性 PostgreSQL MySQL Oracle
许可证 开源(类 MIT) 开源(GPL)/ 商业版 商业收费
SQL 标准兼容性 极高 中等 极高
JSON 支持 JSONB(二进制,可索引) JSON(5.7+) JSON
并发控制 MVCC(优秀) MVCC MVCC
扩展生态 PostGIS、pgvector 等 丰富但有限 商业扩展
适用场景 复杂查询、地理空间、分析 Web 应用(LAMP 栈) 企业级应用

二、为什么选择 PostgreSQL?

  1. SQL 标准兼容性:PostgreSQL 是最接近 SQL 标准的关系型数据库,迁移成本低。
  2. JSONB 支持:可以同时作为关系型数据库和文档数据库使用,减少技术栈复杂度。
  3. 地理空间能力:通过 PostGIS 扩展,PostgreSQL 是业界领先的地理空间数据库。
  4. 社区活跃:版本迭代快,每个大版本都有显著性能提升和新特性。
  5. 云原生支持:各大云厂商(AWS RDS、Google Cloud SQL、Azure Database、阿里云 RDS)都提供托管服务。

三、项目实战:Spring Boot + PostgreSQL CRUD 应用

下面我们基于 postgres-demo 项目,演示如何在实际项目中集成和使用 PostgreSQL。

项目技术栈

  • Java 8 + Spring Boot 2.7.18
  • Spring Data JPA(Hibernate ORM)
  • PostgreSQL 15(Docker 部署)
  • Maven 构建

项目结构

复制代码
postgres-demo/
├── docker-compose.yml          # PostgreSQL + 应用容器编排
├── Dockerfile                  # 应用镜像构建
├── pom.xml                     # Maven 依赖配置
├── src/main/resources/
│   ├── application.yml         # 数据库连接配置
│   └── db/
│       ├── schema.sql          # 建表脚本
│       └── data.sql            # 初始化数据
└── src/main/java/.../
    ├── entity/User.java        # JPA 实体
    ├── repository/UserRepository.java  # 数据访问层
    ├── service/UserService.java        # 业务逻辑层
    └── controller/UserController.java  # REST API

配置数据库连接

yaml 复制代码
# application.yml
spring:
  datasource:
    url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:postgres}
    username: ${DB_USER:postgres}
    password: ${DB_PASSWORD:postgres}
    driver-class-name: org.postgresql.Driver
  jpa:
    hibernate:
      ddl-auto: none      # 手动管理表结构
    show-sql: true
    open-in-view: false
  sql:
    init:
      mode: always
      schema-locations: classpath:db/schema.sql
      data-locations: classpath:db/data.sql

数据库连接信息通过环境变量注入,支持 DB_HOSTDB_PORTDB_NAMEDB_USERDB_PASSWORD,并提供了本地开发的默认值。

数据库表设计

sql 复制代码
-- schema.sql
CREATE TABLE IF NOT EXISTS app_user (
    id BIGSERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL,
    age INT,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
sql 复制代码
-- data.sql
INSERT INTO app_user (username, email, age, created_at) VALUES
    ('zhangsan', 'zhangsan@example.com', 28, NOW()),
    ('lisi', 'lisi@example.com', 32, NOW()),
    ('wangwu', 'wangwu@example.com', 25, NOW())
ON CONFLICT (username) DO NOTHING;

使用 CREATE TABLE IF NOT EXISTSON CONFLICT DO NOTHING 确保脚本幂等,可以安全地重复执行。

JPA 实体映射

java 复制代码
@Entity
@Table(name = "app_user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true, length = 50)
    private String username;

    @Column(nullable = false, length = 100)
    private String email;

    private Integer age;

    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt = LocalDateTime.now();
}
  • GenerationType.IDENTITY 对应 PostgreSQL 的 BIGSERIAL 自增列
  • updatable = false 防止 created_at 被意外修改

数据访问层

java 复制代码
public interface UserRepository extends JpaRepository<User, Long> {
    boolean existsByUsername(String username);
}

继承 JpaRepository 即可获得完整的 CRUD 能力,自定义方法 existsByUsername 由 Spring Data JPA 自动实现。

业务逻辑层

java 复制代码
@Service
@Transactional
public class UserService {
    private final UserRepository userRepository;

    @Transactional(readOnly = true)
    public List<User> findAll() {
        return userRepository.findAll();
    }

    public User create(User user) {
        if (userRepository.existsByUsername(user.getUsername())) {
            throw new IllegalArgumentException("用户名已存在: " + user.getUsername());
        }
        return userRepository.save(user);
    }

    public void delete(Long id) {
        userRepository.deleteById(id);
    }
}
  • 类级别 @Transactional 确保所有方法在事务中执行
  • 查询方法标记 readOnly = true,优化数据库连接
  • 业务校验(如重名校验)在 Service 层完成

REST API 接口

方法 路径 说明
GET /api/users 查询所有用户
GET /api/users/{id} 查询单个用户
POST /api/users 创建用户
PUT /api/users/{id} 更新用户
DELETE /api/users/{id} 删除用户

Docker 一键部署

yaml 复制代码
# docker-compose.yml
services:
  db:
    image: postgres:15-alpine
    container_name: postgres-demo-db
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 10

  app:
    build: .
    container_name: postgres-demo-app
    environment:
      DB_HOST: db
      DB_PORT: 5432
      DB_NAME: postgres
      DB_USER: postgres
      DB_PASSWORD: postgres
    ports:
      - "8080:8080"
    depends_on:
      db:
        condition: service_healthy

运行一条命令即可启动:

bash 复制代码
docker compose up --build

验证 API

bash 复制代码
# 查询所有用户
curl http://localhost:8080/api/users

# 创建新用户
curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{"username":"zhaoliu","email":"zhaoliu@example.com","age":30}'

# 删除用户
curl -X DELETE http://localhost:8080/api/users/1

四、总结

PostgreSQL 是一个功能强大、生态丰富的开源数据库,无论是简单的 CRUD 应用还是复杂的数据分析场景,它都能胜任。通过本文的实战项目,你可以看到:

  1. 使用 Docker Compose 可以轻松搭建 PostgreSQL 开发环境
  2. Spring Boot + Spring Data JPA 提供了简洁的数据库操作方式
  3. 通过 SQL 脚本管理表结构,比 Hibernate 自动 DDL 更可控
  4. 环境变量配置让应用在不同环境(开发、测试、生产)间灵活切换

如果你正在为下一个项目选择数据库,PostgreSQL 绝对值得认真考虑。


项目源码:https://atomgit.com/wangchunyu114/postgres-demo

相关推荐
涛思数据(TDengine)15 分钟前
从_找根因_到_搭系统_:工业 AI 实战直播(十、十一期)
大数据·数据库·人工智能·时序数据库·tdengine
qq_339191141 小时前
mysql磁盘占用排查,mysql存储空间占比统计,mysql判断哪张表占用磁盘空间大
数据库·mysql
东方护航数据恢复(深圳)1 小时前
SSD主控损坏后的芯片级提取:FTL映射表重建与NAND直读
大数据·数据库
光锥智能2 小时前
OceanBase领跑数字政府数据库选型:产品能力、市场潜力、技术潜力均居首
数据库·人工智能·oceanbase
风哥2号2 小时前
达梦DM数据库恢复工具FGDDU(FGEDU DM DUL)
数据库·达梦数据库·数据库恢复
2601_960017623 小时前
啤酒行业PLM突围战:一半科技以配方与工艺数字化重构酿造食品研发体系
数据库·科技·重构
GIS数据转换器3 小时前
智慧林草“一张图“平台
java·大数据·服务器·前端·javascript·数据库·人工智能
gis开发之家3 小时前
Spring Boot 4 深度解析,JdbcTemplate 实战——轻量级数据库操作方案
java·数据库·spring boot·后端