Dbvisitor
dbVisitor is a JDBC-based unified data access layer realizing "One API Access Any DataBase". Its Dual-Layer Architecture bridges RDBMS and NoSQL (MySQL, MongoDB) using standard APIs without new syntax, offering a flexible, abstraction-managed general data foundation for Java applications.
Install / Use
/learn @zycgit/DbvisitorREADME
📖 简介 | Introduction
dbVisitor 是一款基于 JDBC 标准构建的统一数据访问基座,致力于实现 “One APIs Access Any DataBase” 的愿景。 借助独特的双层适配器架构,它成功打破了 RDBMS 与 NoSQL 之间的编程壁垒,让开发者能够使用同一套标准 API 无缝操作 MySQL、MongoDB、Elasticsearch 等各类数据库。 dbVisitor 不主张发明新语法去掩盖差异,而是通过标准化与分层抽象来科学地管理差异,为 Java 应用提供了一个既具备便捷性又保留 JDBC 灵活性的通用数据底座。
<img src="https://www.dbvisitor.net/assets/images/api-levels-78d3da41ab16f3a14b80f564e4a5e18c.jpg" alt="api-levels"/>dbVisitor 提供了多层次的 API 抽象,允许在 简单性 与 灵活性 之间自由切换:
- 🛡 LambdaTemplate: 屏蔽差异
- 类型安全的 Lambda 查询构建器,支持链式调用。
- 单表 CRUD 方法,开箱即用,自动翻译为目标数据库的 SQL 或 DSL。
- 🧱 Mapper/Interface: 管理差异
- 声明式接口编程,支持
@Query/XML,将 SQL/DSL 逻辑与代码分离。 - 提供 BaseMapper 通用方法无需重复开发。
- 声明式接口编程,支持
- 🔧 JdbcTemplate: 透传差异
- 标准 JDBC 模板方法,支持原生 SQL 和 Shell 脚本透传。
- 提供 ConnectionCallback,允许直接访问底层驱动 API。
✨ 核心特性 | Features
<img src="https://www.dbvisitor.net/assets/images/one-api3-1b04529fb64b307aff59db56d1b86b08.jpg" alt="features"/>⚙️ 框架特点 (Framework Characteristics)
- 🛡️ 统一基座: 一套 API 通杀 RDBMS (MySQL, PG...) 与 NoSQL (Mongo, ES...)。
- 🔌 广泛兼容: 纯 Java (JDK8+),零依赖,完美适配 Spring/Solon 等主流框架。
- 📦 轻量级: 极简设计,核心仅依赖
cobble工具包。
🔋 基础能力 (Capabilities)
- API 分层抽象:
- 对象映射:
- SQL Rules:
- 参数处理:
- TypeHandler:
- 接收结果:
- 在所有类型数据源上提供多种方式处理查询结果。
- 常见结果处理有 Bean映射、 RowMapper、 RowCallbackHandler、 ResultSetExtractor
- Session/Transaction:
- 高级特性:
- Map 结构亲和力强,支持多种结果集格式:
- 单值/单列/单行/多行/分页 等多种结果集接收方式。
- 支持返回 List<Map>、Map<K,V>、Set<V>、基本类型数组 等多种数据结构。
- 统一分页接口,自动适配 Limit/ROWNUM/Skip 等方言。
- Map 结构亲和力强,支持多种结果集格式:
- 驱动适配器:
- 可化身为独立的 JDBC Driver,让 MyBatis/Hibernate 也能操作 NoSQL。
- 支持通过标准 JDBC URL 连接各类数据库。
- 已经适配,支持 Redis、 MongoDB、 ElasticSearch 等。
💡 为何选择 dbVisitor? | Why dbVisitor
- 双层适配能力
- 能力加法,dbVisitor 既是数据库访问库也是 JDBC Driver。你可以单独使用其 JDBC Driver,将其放入 Spring Boot + MyBatis 项目中。 让 MyBatis 立刻具备操作 MongoDB 和 Elasticsearch 的能力。
- 底层架构统一
- 不同于简单的拼凑,dbVisitor 在 API 分层抽象 中提供的各级 API 共享 同一套底层机制。 告别多框架产生的缝合怪效应。
- 独立性
- 不绑定任何生态框架 Spring 或任何 Web 容器。基于纯 Java (JDK 8+) 和 JDBC 标准构建。 无论是 Spring、SpringBoot、Solon、Hasor、Guice 还是 Main 方法控制台程序,都能无缝集成。
🚀 使用介绍
1. 引入依赖
<dependency>
<groupId>net.hasor</groupId>
<artifactId>dbvisitor</artifactId>
<version>6.4.0</version> <!-- 请检查 Maven Central 获取最新版本 -->
</dependency>
2. 实战代码
统一 CRUD
无论操作 MySQL 还是 Elasticsearch,代码完全一致:
// 插入数据
template.insert(UserInfo.class)
.applyEntity(new UserInfo("1001", "dbVisitor"))
.executeSumResult();
// 查询数据 (自动翻译为 SQL 或 DSL)
List<UserInfo> list = template.lambdaQuery(UserInfo.class)
.eq(UserInfo::getAge, 18)
.list();
复杂查询 (Mapper 接口)
定义接口,即可享受类似 MyBatis 的开发体验:
@SimpleMapper
public interface UserMapper extends BaseMapper<UserInfo> {
// 方式一:纯 Java 构建 (无需 XML)
default List<UserInfo> findActiveUsers(int minAge) {
return this.query()
.eq(UserInfo::getStatus, "ENABLE")
.gt(UserInfo::getAge, minAge)
.list();
}
// 方式二:注解绑定 (SQL / DSL)
@Query("select * from user_info where age > #{age}")
List<UserInfo> findByAge(@Param("age") int age);
// 方式三:XML 映射 (支持原生 SQL 或 DSL)
// 配合 UserMapper.xml 使用,逻辑分离
List<Map<String, Object>> groupByAge(@Param("minAge") int minAge);
}
XML 映射示例 (UserMapper.xml)
<!-- UserMapper.xml -->
<mapper namespace="com.example.UserMapper">
<select id="groupByAge">
<!-- 编写原生 SQL (MySQL) -->
SELECT age, count(*) FROM user_info
WHERE age > #{minAge} GROUP BY age
<!-- 或者编写 JSON DSL (Elasticsearch) -->
<!--
POST /user_info/_search
{
"query": { "range": { "age": { "gt": #{minAge} } } },
"aggs": { "age_group": { "terms": { "field": "age" } } }
}
-->
</select>
</mapper>
逃生舱 (原生体验)
当所有抽象都无法满足需求时,你可以直接穿透框架:
JdbcTemplate template = ...;
// 1. 原生 SQL/Shell 透传 (直接执行数据库能识别的命令)
// MySQL
template.queryForList("select * from user where id = ?", 1);
// MongoDB (直接写 Mongo Shell)
template.queryForList("db.user.find({_id: ?})", 1);
// 2. 底层 SDK 直达 (Unwrap 机制)
T resultList = jdbcTemplate.execute((ConnectionCallback<T>) con -> {
// 通过标准 JDBC Connection,拆包出底层的原生驱动对象 (如 MongoClient)
if (conn.isWrapperFor(MongoClient.class)) {
MongoClient client = conn.unwrap(MongoClient.class);
// 调用官方 Driver 的任意 API ...
}
return ...;
});
📚 文档与资源 | Resources
- 官方网站: https://www.dbvisitor.net
- 文档指南: https://www.dbvisitor.net/docs/guides
- 博客文章: https://www.dbvisitor.net/blog
📄 许可证 | License
dbVisitor 使用商业友好的 [Apache 2.0](https://www.apache.org/licenses/LICENSE-2
