Apache Empire-db 配置参数详解

系统梳理 Apache Empire-db 的配置项:模型建模、DBDatabaseDriver 方言与连接获取、连接池集成、SQL 生成选项、DBCmdParam 参数绑定、事务处理与 SQL 日志开关。

Apache Empire-dbApache Empire-db2026/10/12

Apache Empire-db 配置参数详解

Apache Empire-db 的配置是编程式的:数据模型、方言、连接与 SQL 行为都由 Java 对象与 JDBC 连接共同决定,不依赖外部配置文件。本文以 2.5.1 为准,逐项说明可配置的模型元素、驱动与连接、SQL 生成选项、参数绑定、事务与日志。

一、配置体系概览

Empire-db 的配置分为四层:

层次承载对象作用
数据模型DBDatabase / DBTable / DBColumn定义库、表、列、主键、索引、外键与关系
方言(驱动)DBDatabaseDriver 及其子类生成目标数据库方言的 SQL、类型转换、DDL
连接JDBC Connection由 DBDatabase.open() 绑定,每次操作显式传入
语句与事务DBCommand / DBCmdParam / Connection参数绑定、PreparedStatement、提交与回滚

一个最小配置示例:

SampleDB db = new SampleDB();                 // 数据模型
DBDatabaseDriver driver = new DBDatabaseDriverH2(); // 方言
Connection conn = DriverManager.getConnection("jdbc:h2:mem:sampledb", "sa", "");
db.open(driver, conn);                        // 绑定方言与连接

二、数据模型配置

2.1 DBDatabase 配置项

DBDatabase 是抽象类,需继承使用。常用配置方法:

方法说明
DBDatabase(String id)构造时指定库标识,同时作为默认 schema 前缀
setSchema(String) / getSchema()显式设置/读取 schema
setLinkName(String)设置数据库链接名(用于跨库引用)
setPreparedStatementsEnabled(boolean)全局开关 PreparedStatement
open(DBDatabaseDriver, Connection)绑定方言驱动与连接
close(Connection)关闭与连接的绑定
getCreateDDLScript(DBDatabaseDriver, DBSQLScript)生成建表 DDL 脚本
createCommand()创建命令对象

示例:

public class SampleDB extends DBDatabase {
    public SampleDB() {
        super("sampledb");
        setPreparedStatementsEnabled(true);
    }
}

2.2 DBTable 配置项

方法说明
new DBTable(String name, DBDatabase db)定义表并注册到库
addColumn(name, DataType, size, DataMode, defValue)添加列
setPrimaryKey(DBColumn...)设置主键(单列/复合)
addIndex(String, DBIndexType, DBColumn...)添加索引(唯一/普通)
addTimestampColumn(String)添加时间戳列
setDefaultCascadeDeleteAction(DBCascadeAction)设置级联删除动作

2.3 DBColumn 与 DataType / DataMode

列的完整定义由四要素构成:名称、数据类型(DataType)、长度(double,含小数位)、数据模式(DataMode)。

常用 DataType:INTEGER、AUTOINC、VARCHAR、TEXT、CHAR、DECIMAL、FLOAT、DATE、DATETIME、TIMESTAMP、BOOL、CLOB、BLOB、UNIQUEID。

DataMode 取值:AutoGenerated(自增/自动生成)、NotNull(必填)、Nullable(可空)。

列级配置方法:setDefaultValue(Object)、setRequired(boolean)、setReadOnly(boolean)、setSize(double)、referenceOn(DBTableColumn)(外键引用)。

示例(含外键):

EMPLOYEES = new DBTable("EMPLOYEES", this);
EMP_DEPT_ID = EMPLOYEES.addColumn("DEPT_ID", DataType.INTEGER, 0, DataMode.NotNull, null);
EMP_DEPT_ID.referenceOn(DEPARTMENTS.DEPT_ID);
EMPLOYEES.setPrimaryKey(EMP_ID);

三、驱动与连接配置

3.1 内置方言驱动

Empire-db 把目标数据库方言封装在 DBDatabaseDriver 的子类中,按数据库选择:

数据库驱动类
H2org.apache.empire.db.h2.DBDatabaseDriverH2
Derbyorg.apache.empire.db.derby.DBDatabaseDriverDerby
HSQLDBorg.apache.empire.db.hsql.DBDatabaseDriverHSql
SQLiteorg.apache.empire.db.sqlite.DBDatabaseDriverSQLite
MySQLorg.apache.empire.db.mysql.DBDatabaseDriverMySQL
PostgreSQLorg.apache.empire.db.postgresql.DBDatabaseDriverPostgreSQL
Oracleorg.apache.empire.db.oracle.DBDatabaseDriverOracle
SQL Serverorg.apache.empire.db.sqlserver.DBDatabaseDriverMSSQL

以 H2 驱动为例,可配置序列相关参数:

DBDatabaseDriverH2 driver = new DBDatabaseDriverH2();
driver.setUseSequenceTable(false);
driver.setSequenceTableName("EMP_SEQUENCES");

3.2 连接获取与生命周期

Empire-db 不自行创建连接,而是接收标准 JDBC Connection:

Connection conn = DriverManager.getConnection("jdbc:h2:mem:sampledb;DB_CLOSE_DELAY=-1", "sa", "");
db.open(driver, conn);
// ... 执行 DDL / CRUD ...
db.close(conn);

除 open/close 外,多数操作(executeUpdate、querySingleInt、DBRecord.read/update、DBReader.open)都要求显式传入 Connection,便于在事务与连接池之间灵活切换。

3.3 连接池集成

由于连接由外部提供,Empire-db 可无缝对接任意连接池(HikariCP、Druid、Tomcat JDBC 等)。使用 HikariCP 提供连接的基本模式:

HikariConfig cfg = new HikariConfig();
cfg.setJdbcUrl("jdbc:h2:mem:sampledb;DB_CLOSE_DELAY=-1");
cfg.setUsername("sa");
cfg.setMaximumPoolSize(5);
DataSource ds = new HikariDataSource(cfg);

try (Connection conn = ds.getConnection()) {
    db.open(driver, conn);
    // ... 数据库操作 ...
}

在 Spring Boot 中只需在 application.properties 中声明数据源,框架自动装配即注入 HikariCP 连接池:

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

实测启动回显(节选):

com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
DataSource 实现: com.zaxxer.hikari.HikariDataSource

四、SQL 方言与生成选项

4.1 方言抽象(getSQLPhrase)

Empire-db 的方言能力集中在 DBDatabaseDriver 上,等价于其他框架的 Dialect。核心方法 getSQLPhrase(int) 返回具体 SQL 片段(如当前时间、字符串拼接、分页伪表等),常量 DBDatabaseDriver.SQL_* 定义了这些片段键;isSupported(DBDriverFeature) 用于探测数据库特性支持情况;setDDLColumnDefaults(boolean) 控制 DDL 是否输出列默认值。需要适配私有数据库时,可继承 DBDatabaseDriver 并覆写上述方法。

4.2 PreparedStatement 开关

db.setPreparedStatementsEnabled(true); // 打开后 DBCommand 生成带 ? 占位符的 SQL

打开后,DBCommand 会以参数占位方式生成 SQL,配合 DBCmdParam 使用,有利于防止 SQL 注入并提升执行计划的复用率。

4.3 DDL 生成选项

getCreateDDLScript(driver, script) 依据当前模型与方言生成建表语句,写入 DBSQLScript:

DBSQLScript script = new DBSQLScript();
db.getCreateDDLScript(driver, script);
for (String stmt : script) System.out.println(stmt);
script.executeAll(driver, conn, false); // 第三个参数为 true 时忽略执行错误

实测生成的 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))

五、DBCommand 参数绑定

DBCommand 支持自动与显式两类参数绑定。

自动绑定:select/set/where 中直接传入的常量会被登记为参数(开启 PreparedStatement 时使用占位符):

DBCommand cmd = db.createCommand();
cmd.select(db.EMP_ID, db.EMP_NAME);
cmd.where(db.EMP_DEPT.is("R&D"));
cmd.where(db.EMP_SALARY.isGreaterThan(new BigDecimal("10000")));

显式绑定:通过 addParam 创建 DBCmdParam,再在条件/赋值中引用:

DBCmdParam minSalary = cmd.addParam(DataType.DECIMAL, new BigDecimal("10000"));
cmd.where(db.EMP_SALARY.isGreaterThan(minSalary));

参数值可通过 cmd.getParamValues() 查看,通过 cmd.getSelect() / getInsert() / getUpdate() / getDelete(table) 获取最终 SQL 文本。

六、事务处理

Empire-db 依赖 JDBC 事务语义,提交与回滚通过 DBDatabase 的 commit/rollback 或直接使用连接:

Connection conn = ds.getConnection();
try {
    conn.setAutoCommit(false);
    db.open(driver, conn);
    DBRecord rec = new DBRecord();
    db.EMPLOYEES.createRecord(rec, conn);
    rec.setValue(db.EMP_NAME, "Dave");
    rec.setValue(db.EMP_SALARY, new BigDecimal("8000.00"));
    rec.update(conn);
    db.commit(conn);          // 提交
} catch (Exception e) {
    db.rollback(conn);        // 回滚
    throw e;
} finally {
    conn.close();
}

要点:Empire-db 不管理事务边界,事务的开启、提交、回滚由应用控制;使用连接池时务必在 finally 中归还连接。

七、SQL 日志开关

Empire-db 使用 SLF4J 输出执行日志。当日志级别为 INFO 时,会打印生成的 SQL 与影响行数;默认无 SLF4J 绑定时仅提示 Failed to load class "org.slf4j.impl.StaticLoggerBinder" 并不输出 SQL。

实测(Spring Boot 默认 INFO 日志)回显:

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
org.apache.empire.db.DBDatabase : Executing: UPDATE sampledb.EMPLOYEES
SET SALARY=11000.00
WHERE ID=2

控制方式:

  • 打开 SQL 日志:引入 slf4j-simple 或 logback-classic 等绑定,并将 org.apache.empire.db 日志级别设为 INFO(或 DEBUG)。
  • 关闭 SQL 日志:将 org.apache.empire.db 级别调至 WARN;相关打印类为 org.apache.empire.db.DBDatabase 与 org.apache.empire.db.DBDDLGenerator。

logback 配置示例:

<logger name="org.apache.empire.db" level="WARN"/>

八、常见问题

Q1:Empire-db 是否有 empire-db.properties 配置文件? 2.5.1 采用编程式配置,没有 properties 配置文件;方言、连接、SQL 选项均在 Java 代码中设置。

Q2:如何切换数据库? 只需更换 DBDatabaseDriver 子类与 JDBC URL,模型代码无需改动。

Q3:如何强制使用 PreparedStatement? 同时设置 db.setPreparedStatementsEnabled(true) 并使用 cmd.addParam(...) 显式绑定参数。

Q4:为什么没有 SQL 日志输出? 缺少 SLF4J 绑定或日志级别高于 INFO;引入绑定并将 org.apache.empire.db 级别设为 INFO 即可。