Apache Empire-db 快速入门与集成示例

从零开始演示 Apache Empire-db 的环境准备、首个 CRUD 程序,并给出在纯 Java 应用与 Spring Boot(HikariCP 连接池)中集成的完整示例代码与真实运行回显,帮助快速上手。

Apache Empire-dbApache Empire-db2026/10/12

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.1Empire-db 核心库
com.h2database:h2:1.4.200H2 内存数据库驱动(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。