本文是《超简单易用的 Java Web 框架 - Javalin》的续篇。
理解了前文所述的基本原理,就能制作一个前后端分离的网站了,但前文没有涉及数据库的问题,下面以 sqlite 为例,说说如何与数据库沟通。
在 pom.xml 中添加以下与数据库操作有关的依赖:
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.39.2.0</version>
</dependency>
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi3-core</artifactId>
<version>3.32.0</version>
</dependency>
为了打通数据库与网站各部分的关系,可以添加 4 个文件,形成非常清晰的结构:
源码参考 github.com/ahui2016/monostich/.../Entry.java
public record Entry(String id, String notes, String cmd, long created) {
Map<String, Object> toMap() {
return Map.of(
"id", id,
"notes", notes,
"cmd", cmd,
"created", created
);
}
}
这里以 Entry 为例,如果数据库里还有别的数据表,则需要创建新的类。
源码参考 github.com/ahui2016/monostich/.../Stmt.java
public class Stmt {
public static final String CREATE_TABLES = """
CREATE TABLE IF NOT EXISTS cmdentry
(
id TEXT PRIMARY KEY COLLATE NOCASE,
notes TEXT NOT NULL,
cmd TEXT NOT NULL,
created INT NOT NULL
);
""";
public static final String GET_ENTRY = """
SELECT * FROM cmdentry WHERE id = :id;
""";
}
源码参考 github.com/ahui2016/monostich/.../DB.java
package com.example.myproject;
public class DB {
private final String dbPath;
private final Jdbi jdbi;
public DB(String dbPath) {
this.path = dbPath;
this.jdbi = Jdbi.create("jdbc:sqlite:" + dbPath);
this.jdbi.useHandle(h -> h.createScript(Stmt.CREATE_TABLES).execute());
this.jdbi.registerRowMapper(ConstructorMapper.factory(Entry.class));
}
void insertEntry(Entry entry) {
jdbi.useHandle(h -> h.createUpdate(Stmt.INSERT_ENTRY)
.bindMap(entry.toMap())
.execute());
}
}
Stmt.CREATE_TABLES
和 Stmt.INSERT_ENTRY
等 SQL 语句集中在一个文件里,很有条理,代码看起来也简明、清晰。insertEntry()
, 点击上面源码参考链接可以看到 getEntry()
, deleteEntry()
等方法,每个方法都很简短。源码参考 github.com/ahui2016/monostich/.../Handle.java
public class Handle {
static DB db = new DB("db/monostich.sqlite");
static void testDB() {
// 插入数据
for (var entry: Mock.entries) {
db.insertEntry(entry);
}
// 获取并在终端打印数据
var entries = db.getAllEntries();
for (var entry: entries) {
Print.ln(entry.toString());
}
// 删除数据
for (var entry: Mock.entries) {
db.deleteEntry(entry.id());
}
// 确认数据已删除
var emptyEntries = db.getAllEntries();
Print.ln("size: " + emptyEntries.size());
}
class Print {
public static void ln(String s) {
System.out.println(s);
}
}
}
Mork.entries
只是一个简单的 Map, 详见上面源码参考链接。如上所示,数据模型 (Entry.java) 与数据表一一对应,然后在 DB.java 里通过 Jdbi 进行数据库操作,最后在 Handle.java 中调用 DB 的方法,形成非常有条理的代码结构。