4.2 Solon 完整集成
依赖
<dependency>
<groupId>top.dlzio</groupId>
<artifactId>dlz-db-solon-plugin</artifactId>
<version>8.0.0</version>
</dependency>
<!-- 下方 DataSource 示例使用 HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
<!-- 下方示例连接 MySQL;使用其他数据库时替换为对应驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
<scope>runtime</scope>
</dependency>
<!-- 使用 Solon 声明式事务 @Tran 时必须显式引入 -->
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-data</artifactId>
<version>3.0.6</version>
</dependency>
Solon 3 Demo 的编译目标是 Java 8。DLZ-DB 插件不会传递 HikariCP、数据库驱动或可选的 solon-data;上面的版本与仓库当前 Solon 3 示例保持一致,升级时应与应用使用的 Solon 版本一起验证。Web 依赖仍按应用需求另行引入。
初始化机制
DlzDbSolonPlugin 通过 Solon SPI 自动加载,无需应用手动调用 Plugin。它会:
- 将
dlz.db绑定为DlzDbProperties。 - 异步等待 Solon 容器中的
DataSourceBean。 - 使用容器中的数据源初始化 DLZ-DB;应用引入
solon-data时,同时对接 Solon 的@Tran事务上下文。
插件不会单凭一段通用 datasource.* YAML 创建数据源。 应用必须自己或通过其他 Solon 数据源插件注册 DataSource Bean。
最小 DataSource 配置
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
config.setJdbcUrl(
"jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=Asia/Shanghai");
config.setUsername("root");
config.setPassword("123456");
return new HikariDataSource(config);
}
}
仓库中的 Solon Demo 使用同样的方式注册 SQLite/HikariCP 数据源。
DLZ-DB 配置
dlz:
db:
logic-delete-field: deleted
sqllist:
- app/*
use-db-sql: false
helper:
auto-update: false
package-name: com.example.entity
log:
show-result: false
show-run-sql: true
show-caller: true
slow-sql-threshold: 1000
helper.auto-update 在生产环境建议保持 false,将 DDL 交给可审核的迁移工具。
使用
@Component
public class UserService {
public List<User> getActiveUsers() {
return DB.pojo.selectWrapper(User.class)
.eq(User::getStatus, 1)
.orderByDesc(User::getCreateTime)
.queryBeanList();
}
}
core 中的 DB.pojo/table/jdbc/sql/batch/ds/tx 用法与 Spring Boot 环境一致。框架自身的 Controller、依赖注入和事务注解仍然按 Solon 规范使用。
事务
@Tran
public void createOrder(Order order, List<OrderItem> items) {
DB.pojo.insert(order);
for (OrderItem item : items) {
item.setOrderId(order.getId());
DB.pojo.insert(item);
}
}
DB.tx.run(() -> {
DB.pojo.insert(order);
DB.pojo.insert(orderItem);
});
@Tran由应用显式引入的solon-data提供;只使用DB.tx.run(...)时不需要该注解。DB.tx.run在同一数据源嵌套时加入外层事务并复用连接。- 当前不提供
REQUIRES_NEW/NESTED语义,也不提供跨数据源原子事务。
同一数据源嵌套时,内层 DB.tx.run 复用外层连接,不独立提交或回滚:
DB.tx.run(() -> {
DB.pojo.insert(order);
DB.tx.run(() -> DB.pojo.insert(orderItem));
});
DLZ-DB 会检测 Solon 原生事务上下文;已有 @Tran 事务时,DB.tx.run 不再建立新的同数据源事务。
事务限制:
- 新建的
DB.tx事务正常返回时提交,抛出异常时回滚并包装为DbException; - 切换到另一数据源后使用另一条连接和独立本地事务,两个数据源之间没有原子协调;
- 不要在事务回调内启动新线程并期待事务自动传播,连接绑定是线程本地的;
- 批量调用不天然表示全有或全无,需要整体回滚时显式放入事务。
通用的数据源注册与编程式事务说明见 3.7 事务与多数据源。
运行时注册多数据源
DataSourceProperty property = new DataSourceProperty();
property.setName("report");
property.setUrl("jdbc:mysql://localhost:3306/report");
property.setUsername("root");
property.setPassword("123456");
property.setDriverClassName("com.mysql.cj.jdbc.Driver");
DB.ds.setDataSource(property);
List<ResultMap> rows = DB.ds.use("report", () ->
DB.jdbc.list("SELECT * FROM daily_report"));
DB.ds.use 只切换数据源上下文;需要事务时使用 DB.tx.run("report", ...)。
预设 SQL
默认 sqllist 为 app/*,对应资源路径 classpath*:sql/app/*.sql。文件虽然使用 .sql 扩展名,内容是 <sqlList> XML 结构。
故障排查
- 启动后 DLZ-DB 未初始化:先确认容器中存在
DataSourceBean。 - 查询时报表不存在:确认手工 DDL,或仅在开发环境开启
helper.auto-update。 - 指定数据源不存在:用
DB.ds.getAllDataSourceNames()检查已注册名称。