SQLite 深度解析:在 Java/Spring 中的使用与嵌入式数据库横向对比
一、SQLite 是什么?
SQLite 是一个嵌入式关系数据库引擎 ,由 D. Richard Hipp 于 2000 年创建,采用公共领域(Public Domain) 许可证。它不是传统的客户端-服务器数据库,而是一个进程内库------直接嵌入到应用程序中,无需独立的数据库进程。
官方口号:Small. Fast. Reliable. Choose any three.
核心特性
- 零配置:无需安装、无需配置、无需管理员
- 服务器less:应用程序直接读写数据库文件,无中间进程
- 单文件存储:整个数据库是一个普通的磁盘文件
- ACID 事务:支持原子提交,即使系统崩溃也能保证数据一致性
- 完整 SQL 实现:支持 CTE、窗口函数、JSON 函数、FTS5 全文搜索等
- 轻量级:完整库体积仅约 600KB(可裁剪至更小)
- 高可靠性:测试覆盖率 100%,有超过 1 亿行测试代码
- 跨平台:支持所有主流操作系统
二、SQLite 与其他嵌入式数据库的对比
嵌入式数据库三巨头:SQLite 、H2 、Apache Derby。此外还有 HSQLDB。以下是深度对比:
| 特性 | SQLite | H2 | Apache Derby | HSQLDB |
|---|---|---|---|---|
| 实现语言 | C | Java(纯) | Java(纯) | Java(纯) |
| 数据库文件 | 单文件 | 单文件 + 可选内存 | 多文件 | 多文件 |
| LICENSE | Public Domain | MPL/EPL | Apache 2.0 | BSD |
| 嵌入方式 | 原生 C,通过 JDBC 桥接 | 原生 JDBC | 原生 JDBC | 原生 JDBC |
| 服务器模式 | 不支持 | 支持 | 支持 | 支持 |
| 内存数据库 | 支持(:memory:) | 支持 | 支持 | 支持 |
| Spring 原生支持 | ❌ 需手动配置 | ✅ 内建支持 | ✅ 内建支持 | ✅ 内建支持 |
| 多进程并发 | ✅ 多进程可读,单写 | ❌ 单进程 | ❌ 单进程 | ❌ 单进程 |
| MVCC | ❌(文件级锁) | ✅ | ✅ | ✅ |
| SQL 标准兼容 | 部分(无 RIGHT/FULL JOIN) | 较好 | 较好 | 较好 |
| 启动速度 | 极快 | 极快 | 较快 | 较快 |
| Java 集成便利性 | 一般(需第三方驱动) | 极佳 | 极佳 | 极佳 |
| 生态/用户量 | 极广(万亿级部署) | 中 | 中 | 中 |
| Hibernate 兼容性 | 需额外配置(Dialect) | 原生支持 | 原生支持 | 原生支持 |
选型建议
选 SQLite 当:
- 需要多进程并发读取同一数据库
- 应用非 Java 语言(C/C++、Python、Go、Rust...)
- 追求极致轻量和零依赖
- 数据库文件需跨语言/跨平台交换
- 移动端、IoT、桌面应用
选 H2/Derby/HSQLDB 当:
- 纯 Java 生态(Spring Boot 内建支持最佳)
- 需要服务器模式以便远程管理
- 需要高性能 MVCC 并发写入
- JPA/Hibernate 重度使用(SQLite 的 Dialect 不完善)
- 开发测试环境需要快速重置数据库
三、SQLite 在 Java/Spring 中的使用
Spring 官方并未将 SQLite 列为内建嵌入式数据库(只支持 H2、HSQL、Derby),但我们依然可以通过第三方驱动和少量配置将其集成进来。
3.1 引入依赖(Maven)
xml
<!-- SQLite JDBC 驱动 -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.46.0.0</version>
</dependency>
推荐同时引入 HikariCP 连接池:
xml
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.1.0</version>
</dependency>
3.2 基础 JDBC 使用
java
import java.sql.*;
public class SQLiteExample {
public static void main(String[] args) throws Exception {
// 1. 加载驱动(3.46.0+ 版本自动注册,可省略)
Class.forName("org.sqlite.JDBC");
// 2. 连接数据库(文件不存在会自动创建)
try (Connection conn = DriverManager.getConnection("jdbc:sqlite:test.db")) {
// 3. 创建表
try (Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE IF NOT EXISTS users (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"name TEXT NOT NULL," +
"email TEXT UNIQUE NOT NULL," +
"created_at TEXT DEFAULT CURRENT_TIMESTAMP)");
}
// 4. 插入数据
String sql = "INSERT INTO users(name, email) VALUES(?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "张三");
pstmt.setString(2, "zhangsan@example.com");
pstmt.executeUpdate();
}
// 5. 查询数据
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
while (rs.next()) {
System.out.printf("%d | %s | %s | %s%n",
rs.getInt("id"),
rs.getString("name"),
rs.getString("email"),
rs.getString("created_at"));
}
}
}
}
}
3.3 在 Spring Boot 中配置 SQLite
yaml
# application.yml
spring:
datasource:
url: jdbc:sqlite:mydb.db
driver-class-name: org.sqlite.JDBC
username:
password:
hikari:
maximum-pool-size: 1 # SQLite 不支持并发写,设为 1
minimum-idle: 1
connection-timeout: 30000
jpa:
database-platform: org.hibernate.community.dialect.SQLiteDialect
hibernate:
ddl-auto: update
show-sql: true
Spring Boot 3.x / Hibernate 6+ 注意 :
SQLiteDialect从 Hibernate 6 起移至org.hibernate.community.dialect包,需额外引入:
xml
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-community-dialects</artifactId>
</dependency>
3.4 使用 JPA(实体映射示例)
java
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false, unique = true)
private String email;
private LocalDateTime createdAt;
// getters / setters ...
}
java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
List<User> findByNameContaining(String keyword);
}
3.5 内存数据库模式
SQLite 支持纯内存数据库,适合测试场景:
java
// JDBC 方式
Connection conn = DriverManager.getConnection("jdbc:sqlite:");
// Spring 配置
spring.datasource.url=jdbc:sqlite:
3.6 WAL 模式------提升并发性能
SQLite 默认使用回滚日志模式(rollback journal),写入时会锁定整个数据库。切换到 WAL(Write-Ahead Log)模式 后,读写可以并发进行:
sql
-- 在连接建立后执行
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;
PRAGMA busy_timeout=5000;
在 Spring 中自动执行:
java
@Configuration
public class SQLiteConfig {
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:sqlite:mydb.db");
config.setDriverClassName("org.sqlite.JDBC");
config.setMaximumPoolSize(1);
config.setConnectionInitSql("PRAGMA journal_mode=WAL");
return new HikariDataSource(config);
}
}
3.7 使用 Spring JDBC 模板
java
@Repository
public class UserDao {
private final JdbcTemplate jdbcTemplate;
public UserDao(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public List<User> findAll() {
return jdbcTemplate.query("SELECT * FROM users",
(rs, rowNum) -> new User(
rs.getLong("id"),
rs.getString("name"),
rs.getString("email"),
rs.getObject("created_at", LocalDateTime.class)
));
}
}
四、SQLite 的关键优化 PRAGMA
| PRAGMA | 说明 | 推荐值 |
|---|---|---|
journal_mode |
日志模式 | WAL(最佳读写并发) |
synchronous |
同步级别 | NORMAL(平衡性能与安全) |
cache_size |
缓存页数(单位:页) | -64000(=64MB) |
page_size |
页大小 | 4096 |
temp_store |
临时存储位置 | MEMORY |
busy_timeout |
忙等待超时(ms) | 5000 |
foreign_keys |
外键约束 | ON(默认关闭,需手动开启) |
五、SQLite 的典型应用场景
- 移动端(Android/iOS 默认数据库)
- 桌面应用(浏览器、编辑器、游戏存档)
- IoT/嵌入式设备(资源受限环境)
- 应用文件格式(替代 XML/JSON 作为数据存储格式)
- 开发/测试阶段(快速原型,无需安装数据库)
- 数据分析/ETL 中间存储
- 浏览器、Chrome/Firefox 内部存储
六、SQLite 的局限性
- ❌ 不支持并发写入(WAL 模式下可读写并发,但仍不支持多写)
- ❌ 不支持存储过程、用户自定义函数(UDF 需编译 C 扩展)
- ❌ 不支持 RIGHT/FULL OUTER JOIN
- ❌ 不支持 GRANT/REVOKE 权限管理
- ❌ 不适合高并发 OLTP 场景
- ❌ 不适合超大规模数据(单库推荐 < 140TB,实际 < 10TB 更佳)
- ❌ Hibernate/JPA 集成体验不如 H2/Derby(Dialect 非官方,部分特性不支持)
七、总结
SQLite 是世界上部署最广泛的数据库引擎 (没有之一),每个智能手机都有数百个 SQLite 数据库。它是一款极致轻量、零依赖、跨语言的嵌入式数据库。
在 Java/Spring 生态中,如果项目是纯 Java 且不需要多进程共享 ,H2 往往是更好的选择(Spring 原生支持、更好的 Hibernate 兼容性、内置控制台)。但如果需要跨语言共享数据文件、多进程并发读取、或部署在资源受限环境,SQLite 仍是不可替代的选择。
简单决策树:
- 纯 Java 微服务 / 测试环境 → H2
- 移动端 / IoT → SQLite
- 桌面应用 / 单用户软件 → SQLite (更轻量)或 H2(需远程管理时)
- 多进程读写同一数据库 → SQLite(WAL 模式)
- 需要服务器模式远程连接 → H2 / Derby
参考链接: