New MongoDB ORM/ODM Tool
This article is generated by AI translation.
Java ORM tools are mature for RDBMS, but MongoDB's document model needs ODM (Object-Document Mapping) for clean Java integration. This post surveys the landscape and introduces dbVisitor as a JDBC-based solution.
Why ORM/ODM?
MongoDB stores flexible BSON documents, but in Java we face:
- Type safety: Working directly with
DocumentorMapis error-prone and hard to maintain. - Domain models: Business logic is built on POJOs; we need automatic (de)serialization.
- Developer efficiency: Hand-writing BSON builders is clumsy compared to object-centric operations.
- Unified style: Projects often mix RDBMS and MongoDB; a consistent API style lowers cognitive load.
ORM vs ODM
- ORM (Object-Relational Mapping): Bridges OO models and relational tables (MySQL, Oracle, etc.).
- ODM (Object-Document Mapping): Bridges Java objects and document databases (MongoDB, Elasticsearch, etc.). BSON naturally supports nested structures, so ODM mappings can be simpler, though references are handled differently.
In short: ORM maps “tables,” ODM maps “documents.”
dbVisitor for MongoDB
dbVisitor is a database access toolkit that provides a full JDBC driver for MongoDB (jdbc-mongo). You can operate MongoDB like MySQL using JDBC, raw commands, or MyBatis-style mappers. The Mongo adapter even lets you perform CRUD without writing Mongo commands.
Features
- JDBC protocol: Standard JDBC driver (jdbc-mongo); works with any JDBC ecosystem (e.g., HikariCP). Build parameterized queries with
PreparedStatement. - Raw commands: Execute native MongoDB commands to reduce the learning curve.
- Multiple APIs:
- JdbcTemplate for direct commands and unstructured data.
- LambdaTemplate for type-safe builders (MyBatis-Plus–style LambdaQueryWrapper).
- Mapper interfaces with annotations (
@Insert,@Query) or XML—fully MyBatis-compatible.
- Dynamic Command: Use
<if>,<foreach>,<where>, etc., in XML or annotations to build complex conditions. Choose raw commands for complex queries or LambdaTemplate for single-collection CRUD.
Tool comparison
| Feature | MongoClient | Spring Data MongoDB | Morphia | MongoPlus | dbVisitor |
|---|---|---|---|---|---|
| Positioning | Official low-level driver | Spring ODM | Lightweight ODM | MyBatis-Plus style | JDBC driver + ORM (no MyBatis dependency) |
| Dependency level | None (base lib) | Strong Spring dependency | Low | Spring required for full features | Very low (only official driver) |
| API style | BSON/Builder | Repository / Template | Annotation / Datastore | Lambda / Mapper | JDBC / Template / Lambda / Mapper / Annotation |
| Query language | BSON Filters | Criteria / Query Methods | Fluent API | Fluent API | Fluent API / Query Methods / Raw commands |
| Learning curve | High (API-heavy) | Medium (Spring Data) | High (API-heavy) | Medium (MyBatis & MyBatis-Plus) | Low (MyBatis / Spring JDBC / native commands) |
| Dynamic Command | Manual BSON | Weak | Not supported | Not supported | Strong (XML dynamic tags / rules) |
| JDBC support | None | None | None | None | Native |
| Multi-data-source | Not supported | Needs other Spring modules | Not supported | Not supported | MongoDB, Redis, MySQL, PostgreSQL, Oracle, etc. |
Recommendations
- Need maximum performance and don’t mind writing BSON? Or the project is very simple? Use MongoClient.
- Deep in the Spring ecosystem and prefer Repository patterns? Choose Spring Data MongoDB.
- Prefer the MyBatis style, want XML-managed commands, or need MongoDB in legacy systems lacking NoSQL support? dbVisitor is a strong, practical choice.
dbVisitor bridges RDBMS and NoSQL via JDBC and a unified API, reducing cognitive and maintenance costs in mixed database architectures.
How to use
1) Add dependencies
Add core and MongoDB adapter (Java 8). Current version: 6.7.0
<dependencies>
<dependency>
<groupId>net.hasor</groupId>
<artifactId>dbvisitor</artifactId>
<version>6.3.0</version>
</dependency>
<dependency>
<groupId>net.hasor</groupId>
<artifactId>jdbc-mongo</artifactId>
<version>>6.3.0</version>
</dependency>
</dependencies>
Connection URL example: jdbc:dbvisitor:mongo://127.0.0.1:27017/admin?user=root&password=123456.
2) Raw Mongo commands
Good for full control or quick debugging.
try (Connection c = DriverManager.getConnection(url, user, pwd)) {
JdbcTemplate jdbc = new JdbcTemplate(c);
// Insert
jdbc.execute("db.users.insertOne({name: ?, age: ?})", "Alice", 18);
// Query
Map<String, Object> row = jdbc.queryForMap("db.users.findOne({name: ?})", "Alice");
}
3) Mapper interfaces
Annotate commands to stay in the MyBatis style.
public interface UserMapper {
@Insert("db.users.insertOne({name: :name, age: :age})")
int insert(User user);
@Query("db.users.find({age: {$gt: :age}})")
List<User> findByAge(@Param("age") int age);
}
UserMapper mapper = lambda.getMapper(UserMapper.class);
mapper.insert(new User("Cindy", 22));
4) CRUD builders
No need to handcraft commands; write conditions against entities.
public class User {
private String name;
private int age;
// getters/setters omitted
}
try (Connection c = DriverManager.getConnection(url, user, pwd)) {
User u = new User();
u.setUserId(123);
u.setName("Alice");
u.setAge(18);
LambdaTemplate lambda = new LambdaTemplate(c);
int r1 = lambda.insert(User.class)
.applyEntity(u)
.executeSumResult();
List<User> list = lambda.query(User.class)
.eq(User::getAge, 18)
.queryForList();
// Query by PK
User u2 = lambda.query(User.class)
.eq(User::getUserId, u.getUserId())
.queryForObject();
// Update
int r2 = lambda.update(User.class)
.updateTo(User::getName, 20)
.eq(User::getUserId, u.getUserId())
.doUpdate();
// Delete
int r3 = lambda.delete(User.class)
.eq(User::getUserId, u.getUserId())
.doDelete();
}
5) Map entities
Use @Table / @Column to map collections and fields; supports primary keys, aliases, and TypeHandler.
@Table("users")
public class User {
@Column(value = "userId", primary = true)
private String userId;
@Column("name")
private String name;
@Column("age")
private Integer age;
// getters/setters omitted
}
6) Mapper files
Best for complex dynamic conditions; can coexist with annotations.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//dbvisitor.net//DTD Mapper 1.0//EN"
"https://www.dbvisitor.net/schema/dbvisitor-mapper.dtd">
<mapper namespace="net.hasor.scene.mongodb.dto.UserMapper">
<insert id="saveUser">
db.users.insertOne({name: :name, age: :age})
</insert>
<select id="loadUser" resultType="net.hasor.scene.mongodb.dto.User">
db.users.find({name: #{name}})
</select>
<delete id="deleteUser">
db.users.remove({name: #{name}})
</delete>
</mapper>
@RefMapper("dbvisitor/mapper/user-mapper.xml")
public interface UserMapper {
int saveUser(User info);
User loadUser(@Param("name") String name);
int deleteUser(@Param("name") String name);
}
7) Picking an API
- JdbcTemplate: maximum freedom for debugging, special commands, or pipelines.
- Mapper interfaces: light config; good for small/mid projects or fixed statements.
- LambdaTemplate: type-safe, no template strings; ideal for standard CRUD and medium complexity.
- Mapper XML: strongest dynamic command; best for complex queries/aggregations and combinations.
- @Table/@Column: when you need entity-to-document mapping, aliases, or TypeHandlers.
Framework integration
Quick integration examples (see 3.3 Spring Integration for details).
Spring Boot
Add dependencies first. Current version: 6.7.0
<dependency>
<groupId>net.hasor</groupId>
<artifactId>dbvisitor-spring-starter</artifactId>
<version>6.3.0</version>
</dependency>
<dependency>
<groupId>net.hasor</groupId>
<artifactId>jdbc-mongo</artifactId>
<version>>6.3.0</version>
</dependency>
Option 1: configure application.properties
# Spring JDBC data source
spring.datasource.url=jdbc:dbvisitor:mongo://127.0.0.1:27017/admin
spring.datasource.username=root
spring.datasource.password=123456
# Required
dbvisitor.mapper-packages=com.example.demo.dao
dbvisitor.mapper-locations=classpath:dbvisitor/mapper/*.xml
Option 2: configure via annotations on the bootstrap class
@Configuration
@MapperScan(basePackages = "com.example.demo.dao",
mapperLocations = "classpath:dbvisitor/mapper/*.xml")
public class DemoApplication {
...
}
Injecting mappers
import net.hasor.dbvisitor.lambda.LambdaTemplate;
import net.hasor.dbvisitor.jdbc.core.JdbcTemplate; // different from Spring's JdbcTemplate
import javax.annotation.Resource;
public class ServiceTest {
@Resource // or @Autowired
private UserMapper userMapper;
@Resource // or @Autowired
private JdbcTemplate jdbc;
@Resource // or @Autowired
private LambdaTemplate lambda;
...
}
Summary
dbVisitor brings MongoDB into the same developer experience as relational databases via JDBC. Use raw commands, type-safe Lambda, annotation/XML mappers, or zero-command CRUD. Pick the API that fits the scenario to balance speed, safety, and maintainability. Mixing RDBMS and MongoDB under one API lowers team cognitive load.