Spring Boot 整合 SQLite 数据库

SQLite 是一种嵌入式关系型数据库管理系统(RDBMS),使用 C 语言开发,以其简单性、轻量级和零配置而闻名。不需要独立的服务器,可以直接嵌入到应用中。支持事务,支持各种编程语言。是移动应用和嵌入式系统的首选数据库解决方案。

本文将会带你了解如何在 Spring Boot 中配置和使用 SQLite。

创建 Spring Boot 应用

创建一个示例 Spring Boot 应用。在 pom.xml 添加 spring-boot-starter-jdbc 和 SQLite 驱动 sqlite-jdbc 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>org.xerial</groupId>
    <artifactId>sqlite-jdbc</artifactId>
</dependency>

sqlite-jdbc 已经被 Spring Boot 纳入了版本控制,所以在项目继承了 spring-boot-starter-parent 的情况下,添加此依赖不用声明版本号。

配置属性

application.yaml 中配置如下属性:

spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: org.sqlite.JDBC
    url: "jdbc:sqlite:D:\\app.db"

使用默认的数据源实现 HikariDataSource。通过 driver-class-name属性指定 SQLite 的驱动类。url 配置指定了 SQLite 数据库文件的位置,可以是相对路径或者绝对路径。如果文件不存在,会被创建。

测试

得益于 Spring Boot 对数据源开箱即用的支持,完成上述配置后,SQLite 数据库已经就绪可以使用了。

创建测试类:

import java.time.LocalDateTime;
import java.util.Map;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;


@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class DemoApplicationTests {

    static final Logger log = LoggerFactory.getLogger(DemoApplicationTests.class);

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Test
    public void test() throws Exception {
        // 1、首先创建数据表
        String ddl = """
            CREATE TABLE `user` (
                id INTEGER PRIMARY KEY NOT NULL,
                name TEXT,
                create_at TEXT
            );
        """;
        
        this.jdbcTemplate.execute(ddl);

        // 2、插入一条数据
        int ret = this.jdbcTemplate.update("INSERT INTO `user` (`id`, `name`, `create_at`) VALUES (?, ?, ?);", new Object[] {1, "springdoc", LocalDateTime.now()});
        
        log.info("插入数据:{}", ret);
        
        // 3、检索一条数据
        Map<String, Object> user = this.jdbcTemplate.queryForObject("SELECT * FROM `user` WHERE `id` = ?", new ColumnMapRowMapper(), 1L);
        
        log.info("检索数据:{}", user);
    }
}

首先,在测试类中注入 JdbcTemplate,这是由 Spring Data Jdbc Stater 自动配置的,用于操作 SQLite 数据库。

接着,执行 DDL 语句,在数据库中创建 user 表,有三个字段 idnamecreate_at,其中 id 是 INTEGER 类型、主键且不能为 NULL。后面两个字段则都是 TEXT 类型。

DDL 语句的声明使用了 JDK 15 引入的新特性 “文本块”。

然后,执行 INSERT 语句,往表中插入一条记录,通过 ? 占位符绑定位置参数,返回受影响的行数。

最后,执行 SELECT 查询,从数据库中检索上一步插入的记录。使用 ColumnMapRowMapper Mapper 把查询结果封装为 Map<String, Object>,key 是列名称,value 是对应的值。

SQLite 没有一个单独的用于存储日期、时间的类型。但 SQLite 能够把日期和时间存储为 TEXT、REAL 或 INTEGER 值。

  • TEXT:格式为 “YYYY-MM-DD HH:MM:SS.SSS” 的日期。
  • REAL:从公元前 4714 年 11 月 24 日格林尼治时间的正午开始算起的天数。
  • INTEGER:从 1970-01-01 00:00:00 UTC 算起的秒数。

执行测试,控制台输出的日志如下:

INFO 18800 --- [           main] c.s.demo.test.DemoApplicationTests       : 插入数据:1
INFO 18800 --- [           main] c.s.demo.test.DemoApplicationTests       : 检索数据:{id=1, name=springdoc, create_at=2023-11-14T19:28:17.135435300}

输出结果符合预期,整合成功。