愿景 “One API Access Any DataBase”
一款数据库访问库,提供 Java 对多种不同类型数据库统一访问,它的目标是使用一套 API 访问所有数据库。
Website • Documentation • Blog
dbVisitor 是一款基于 JDBC 标准构建的统一数据访问基座,致力于实现 “One API Access Any DataBase” 的愿景。 借助独特的双层适配器架构,它成功打破了 RDBMS 与 NoSQL 之间的编程壁垒,让开发者能够使用同一套标准 API 无缝操作 MySQL、MongoDB、Elasticsearch 等各类数据库。 dbVisitor 不主张发明新语法去掩盖差异,而是通过标准化与分层抽象来科学地管理差异,为 Java 应用提供了一个既具备便捷性又保留 JDBC 灵活性的通用数据底座。
dbVisitor 提供了多层次的 API 抽象,允许在 简单性 与 灵活性 之间自由切换:
- 🛡 LambdaTemplate: 屏蔽差异
- 类型安全的 Lambda 查询构建器,支持链式调用。
- 单表 CRUD 方法,开箱即用,自动翻译为目标数据库的 SQL 或 DSL。
- 🧱 Mapper/Interface: 管理差异
- 声明式接口编程,支持
@Query/XML,将 SQL/DSL 逻辑与代码分离。 - 提供 BaseMapper 通用方法无需重复开发。
- 声明式接口编程,支持
- 🔧 JdbcTemplate: 透传差异
- 标准 JDBC 模板方法,支持原生 SQL 和 Shell 脚本透传。
- 提供 ConnectionCallback,允许直接访问底层驱动 API。
- 🛡️ 统一基座: 一套 API 通杀 RDBMS (MySQL, PG...) 与 NoSQL (Mongo, ES...)。
- 🔌 广泛兼容: 纯 Java (JDK8+),零依赖,完美适配 Spring/Solon 等主流框架。
- 📦 轻量级: 极简设计,核心仅依赖
cobble工具包。
- 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 既是数据库访问库也是 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 方法控制台程序,都能无缝集成。
<dependency>
<groupId>net.hasor</groupId>
<artifactId>dbvisitor</artifactId>
<version>6.4.0</version> <!-- 请检查 Maven Central 获取最新版本 -->
</dependency>无论操作 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();定义接口,即可享受类似 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);
}<!-- 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 ...;
});- 官方网站: https://www.dbvisitor.net
- 文档指南: https://www.dbvisitor.net/docs/guides
- 博客文章: https://www.dbvisitor.net/blog
dbVisitor 使用商业友好的 Apache 2.0 许可协议。

