Apache Empire-db 快速入门与集成示例
从零开始演示 Apache Empire-db 的环境准备、首个 CRUD 程序,并给出在纯 Java 应用与 Spring Boot(HikariCP 连接池)中集成的完整示例代码与真实运行回显,帮助快速上手。
Apache Empire-db 快速入门与集成示例
本文从零开始,先完成一个 Apache Empire-db 的最小 CRUD 程序,再分别给出「纯 Java 应用分层集成」与「Spring Boot + HikariCP 集成」的完整示例与运行回显。示例以 2.5.1 + H2 内存库为准,JDK 8/11/17 均可运行。
一、环境准备
- JDK 8/11/17 任选其一(示例编译目标为 8)。
- Maven 3.5+。
- 服务器具备
root权限,示例账号root/q1w2e3r4。 - 建议 JVM 堆内存 256–512MB(示例用
-Xmx512m)。
工程依赖坐标:
| 坐标 | 说明 |
|---|---|
org.apache.empire-db:empire-db:2.5.1 | Empire-db 核心库 |
com.h2database:h2:1.4.200 | H2 内存数据库驱动(JDK 8 兼容) |
二、第一个 Empire-db 程序
2.1 工程与依赖
mkdir -p /root/empiredb-demo/src/main/java/demo
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>empiredb-demo</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.empire-db</groupId>
<artifactId>empire-db</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
</dependencies>
</project>
2.2 定义数据模型
public static class SampleDB extends DBDatabase {
private static final long serialVersionUID = 1L;
public final DBTable EMPLOYEES;
public final DBTableColumn EMP_ID, EMP_NAME, EMP_DEPT, EMP_SALARY;
public SampleDB() {
super("sampledb");
EMPLOYEES = new DBTable("EMPLOYEES", this);
EMP_ID = EMPLOYEES.addColumn("ID", DataType.AUTOINC, 0, DataMode.AutoGenerated, null);
EMP_NAME = EMPLOYEES.addColumn("NAME", DataType.TEXT, 80, DataMode.NotNull, null);
EMP_DEPT = EMPLOYEES.addColumn("DEPT", DataType.TEXT, 40, DataMode.Nullable, null);
EMP_SALARY = EMPLOYEES.addColumn("SALARY", DataType.DECIMAL, 10.2, DataMode.Nullable, null);
EMPLOYEES.setPrimaryKey(EMP_ID);
}
}
2.3 CRUD 主流程
SampleDB db = new SampleDB();
DBDatabaseDriver driver = new DBDatabaseDriverH2();
Connection conn = DriverManager.getConnection("jdbc:h2:mem:sampledb;DB_CLOSE_DELAY=-1", "sa", "");
try (java.sql.Statement st = conn.createStatement()) {
st.execute("CREATE SCHEMA IF NOT EXISTS sampledb"); // Empire-db 以库标识为 schema
}
db.open(driver, conn);
// 建表
DBSQLScript ddl = new DBSQLScript();
db.getCreateDDLScript(driver, ddl);
ddl.executeAll(driver, conn, false);
// 插入
DBRecord rec = new DBRecord();
db.EMPLOYEES.createRecord(rec, conn);
rec.setValue(db.EMP_NAME, "Alice");
rec.setValue(db.EMP_DEPT, "R&D");
rec.setValue(db.EMP_SALARY, new BigDecimal("12000.50"));
rec.update(conn);
// 查询
DBCommand q = db.createCommand();
q.select(db.EMP_ID, db.EMP_NAME, db.EMP_DEPT, db.EMP_SALARY);
q.where(db.EMP_SALARY.isGreaterThan(new BigDecimal("10000")));
q.orderBy(db.EMP_ID);
DBReader reader = new DBReader();
reader.open(q, conn);
while (reader.moveNext()) { /* reader.getValue(0..3) */ }
reader.close();
2.4 运行结果解读
mvn -q compile
LANG=C.UTF-8 java -Xmx512m -Dfile.encoding=UTF-8 -cp "target/classes:lib/*" demo.EmpireDbDemo
真实回显:
Empire-db 版本: 2.5.1
== 1. 生成建表 DDL 并执行 ==
-- creating table EMPLOYEES --
CREATE TABLE sampledb.EMPLOYEES (
ID INT AUTO_INCREMENT NOT NULL,
NAME VARCHAR(80) NOT NULL,
DEPT VARCHAR(40),
SALARY DECIMAL(10,2),
PRIMARY KEY (ID))
== 2. 插入 INSERT ==
已插入: ID=1 NAME=Alice DEPT=R&D SALARY=12000.50
已插入: ID=2 NAME=Bob DEPT=Sales SALARY=9000.00
已插入: ID=3 NAME=Carol DEPT=R&D SALARY=15000.75
插入后总行数: 3
== 3. 查询 SELECT (SALARY > 10000, 按 ID 升序) ==
ID NAME DEPT SALARY
1 Alice R&D 12000.50
3 Carol R&D 15000.75
命中行数: 2
== 4. 更新 UPDATE (Bob 调薪 + 转岗) ==
更新后: ID=2 NAME=Bob DEPT=R&D SALARY=11000.00
== 5. 删除 DELETE (Carol 离职) ==
删除 ID=3 后总行数: 2
== 6. 参数绑定查询 (DBCmdParam) ==
R&D 部门成员: Alice Bob
完成: Empire-db CRUD 闭环验证通过。
解读要点:Empire-db 从模型直接生成方言 DDL;AUTOINC 列插入后可由 rec.getValue(EMP_ID) 取回自增主键;DBReader 按 select 顺序通过下标取值;查询条件 isGreaterThan、排序 orderBy 均以类型安全的表达式书写。
三、集成示例:纯 Java 应用分层
把数据访问封装到 DAO,业务层只面对方法调用。
3.1 DAO 封装
public class EmployeeDao {
private final DataSource dataSource;
private final SampleDB db = new SampleDB();
private final DBDatabaseDriver driver = new DBDatabaseDriverH2();
public EmployeeDao(DataSource dataSource) {
this.dataSource = dataSource;
}
public int insert(String name, String dept, BigDecimal salary) throws SQLException {
try (Connection conn = dataSource.getConnection()) {
db.open(driver, conn);
DBRecord rec = new DBRecord();
db.EMPLOYEES.createRecord(rec, conn);
rec.setValue(db.EMP_NAME, name);
rec.setValue(db.EMP_DEPT, dept);
rec.setValue(db.EMP_SALARY, salary);
rec.update(conn);
return (Integer) rec.getValue(db.EMP_ID);
}
}
}
3.2 调用与结果
DAO 通过 DataSource 取连接,天然对接连接池;每次操作后连接归还池中。调用方式与第二节主流程一致,输出同上。
四、集成示例:Spring Boot
Spring Boot 2.7 自动装配 DataSource(默认 HikariCP),把 DataSource 注入 DAO 即可让 Empire-db 使用连接池。
4.1 依赖与配置
pom.xml(关键部分):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.empire-db</groupId>
<artifactId>empire-db</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
application.properties:
spring.datasource.url=jdbc:h2:mem:springdb;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.hikari.maximum-pool-size=5
spring.datasource.hikari.minimum-idle=1
4.2 DAO 与运行类
EmployeeDao 用构造器注入 DataSource,在初始化时用 Empire-db 生成并执行建表 DDL:
@Component
public class EmployeeDao {
public static class SampleDB extends DBDatabase { /* 同第二节模型 */ }
private final DataSource dataSource;
private final SampleDB db = new SampleDB();
private final DBDatabaseDriver driver = new DBDatabaseDriverH2();
public EmployeeDao(DataSource dataSource) {
this.dataSource = dataSource;
initSchema();
}
private void initSchema() {
try (Connection conn = dataSource.getConnection()) {
try (java.sql.Statement st = conn.createStatement()) {
st.execute("CREATE SCHEMA IF NOT EXISTS sampledb");
}
db.open(driver, conn);
DBSQLScript ddl = new DBSQLScript();
db.getCreateDDLScript(driver, ddl);
try { ddl.executeAll(driver, conn, false); }
catch (Exception alreadyExists) { /* 表已存在则忽略 */ }
} catch (SQLException e) {
throw new IllegalStateException("初始化 schema 失败", e);
}
}
public int count() throws SQLException {
try (Connection conn = dataSource.getConnection()) {
DBCommand c = db.createCommand();
c.select(db.EMPLOYEES.count());
return db.querySingleInt(c, conn);
}
}
}
启动类通过 CommandLineRunner 触发一次完整 CRUD:
@SpringBootApplication
public class EmpireDbSpringApp {
public static void main(String[] args) {
SpringApplication.run(EmpireDbSpringApp.class, args);
}
@Bean
CommandLineRunner runner(EmployeeDao dao, DataSource ds) {
return args -> {
System.out.println("DataSource 实现: " + ds.getClass().getName());
dao.insert("Alice", "R&D", new BigDecimal("12000.50"));
dao.insert("Bob", "Sales", new BigDecimal("9000.00"));
dao.insert("Carol", "R&D", new BigDecimal("15000.75"));
System.out.println("插入后总行数: " + dao.count());
for (String row : dao.findAllOrderById()) System.out.println(row);
dao.updateSalary("Bob", new BigDecimal("11000.00"));
dao.deleteByName("Carol");
System.out.println("删除 Carol 后总行数: " + dao.count());
};
}
}
4.3 运行与真实回显
mvn -q -B package -DskipTests
LANG=C.UTF-8 java -Xmx512m -Dfile.encoding=UTF-8 -jar target/empiredb-spring-1.0.0.jar
真实回显(节选):
:: Spring Boot :: (v2.7.18)
org.apache.empire.db.DBDatabase : Instance of database demo.spring.EmployeeDao$SampleDB registered with instanceid=SampleDB
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
org.apache.empire.db.DBDDLGenerator : Adding create statmement for table EMPLOYEES.
== Spring Boot + Empire-db 集成验证 ==
DataSource 实现: com.zaxxer.hikari.HikariDataSource
org.apache.empire.db.DBDatabase : Executing: INSERT INTO sampledb.EMPLOYEES( NAME, DEPT, SALARY) VALUES ( 'Alice', 'R&D', 12000.50)
org.apache.empire.db.DBDatabase : executeSQL affected 1 Records in 22 ms
插入后总行数: 3
---- 全量查询 ----
1 Alice R&D 12000.50
2 Bob Sales 9000.00
3 Carol R&D 15000.75
org.apache.empire.db.DBDatabase : Executing: UPDATE sampledb.EMPLOYEES
SET SALARY=11000.00
WHERE ID=2
Bob 调薪后总行数: 3
org.apache.empire.db.DBDatabase : Executing: DELETE FROM sampledb.EMPLOYEES
WHERE ID=3
删除 Carol 后总行数: 2
== 集成验证完成 ==
可见:Spring Boot 注入的 DataSource 为 HikariDataSource;Empire-db 在 INFO 级别打印生成的 SQL 与影响行数,便于观测与排错;CRUD 结果与纯 Java 版本一致。
五、常见问题
Q1:Empire-db 与 MyBatis/JPA 有何区别? Empire-db 用 Java 对象定义模型并生成 SQL,介于「全手写 SQL」与「全自动 ORM」之间,强调类型安全与可重构,不需要 XML 映射或注解实体。
Q2:Spring Boot 中需要额外配置吗?
只需提供 DataSource(Spring Boot 自动装配),把连接交给 Empire-db 的 open(driver, conn) 或各操作方法即可。
Q3:切换数据库要改哪些地方?
只需更换 DBDatabaseDriver 子类与 JDBC URL;数据模型与业务代码不变。
Q4:为什么日志里没有 SQL?
默认无 SLF4J 绑定时不输出;引入绑定并把 org.apache.empire.db 级别设为 INFO 即可看到生成的 SQL。