Apache Empire-db 配置参数详解
系统梳理 Apache Empire-db 的配置项:模型建模、DBDatabaseDriver 方言与连接获取、连接池集成、SQL 生成选项、DBCmdParam 参数绑定、事务处理与 SQL 日志开关。
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 的子类中,按数据库选择:
| 数据库 | 驱动类 |
|---|---|
| H2 | org.apache.empire.db.h2.DBDatabaseDriverH2 |
| Derby | org.apache.empire.db.derby.DBDatabaseDriverDerby |
| HSQLDB | org.apache.empire.db.hsql.DBDatabaseDriverHSql |
| SQLite | org.apache.empire.db.sqlite.DBDatabaseDriverSQLite |
| MySQL | org.apache.empire.db.mysql.DBDatabaseDriverMySQL |
| PostgreSQL | org.apache.empire.db.postgresql.DBDatabaseDriverPostgreSQL |
| Oracle | org.apache.empire.db.oracle.DBDatabaseDriverOracle |
| SQL Server | org.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 即可。