MongoDB the MyBatis Way
This article is generated by AI translation.
In hybrid projects with both MySQL and MongoDB, the data access layer often feels fragmented — MyBatis Mapper on one side, MongoTemplate on the other. dbVisitor lets you operate MongoDB using the same Mapper interfaces and XML, achieving a unified architecture.
1. Pain Points of Traditional Approaches
In traditional hybrid architectures, we might encounter the following problems:
- Inconsistent API Styles: RDBMS uses SQL, while MongoDB uses BSON and proprietary protocols.
- Differences in Pagination Implementation: MyBatis is usually paired with PageHelper, while MongoDB requires manually calculating
skipandlimit. - High Maintenance Costs: Maintaining two completely different underlying logics increases code complexity and the probability of errors.
2. dbVisitor's Solution
dbVisitor encapsulates MongoDB operations into standard JDBC interfaces by providing a JDBC driver layer (dbvisitor-driver) and an adapter (jdbc-mongo). This means you can operate MongoDB just like you operate MySQL.
Furthermore, dbVisitor provides ORM features similar to MyBatis, supporting Mapper interfaces, XML mapping files, annotations, and Lambda expressions.
2.1 Object Relational Mapping (ORM)
First, we define a Java object and map it using annotations. This is very similar to MyBatis Plus or JPA.
@Table("user_info")
public class UserInfo {
// Map _id field and automatically handle ObjectId
@Column(value = "_id", primary = true, keyType = KeyType.Auto, whereValueTemplate = "ObjectId(?)")
private String id;
@Column("name")
private String name;
@Column("age")
private Integer age;
// getters/setters omitted
}
2.2 Using Mapper Interface (Annotation Style)
You can define a Mapper interface and use annotations to write MongoDB commands.
@SimpleMapper
public interface UserInfoMapper {
// Insert data
@Insert("test.user_info.insert(#{info})")
int saveUser(@Param("info") UserInfo info);
// Query by ID
@Query("test.user_info.find({_id: ObjectId(#{id})})")
UserInfo loadById(@Param("id") String id);
// Delete data
@Delete("test.user_info.remove({_id: ObjectId(#{id})})")
int deleteUser(@Param("id") String id);
}
2.3 Using Common Mapper
If you don't want to write any commands, you can directly inherit BaseMapper, and dbVisitor will automatically generate basic CRUD operations.
@SimpleMapper
public interface UserInfoBaseMapper extends BaseMapper<UserInfo> {
// Automatically possesses methods like insert, update, delete, selectById, listBySample, etc.
}
2.4 Using Lambda Style
dbVisitor also provides a Lambda call style similar to MyBatis Plus, which is completely type-safe.
LambdaTemplate lambda = new LambdaTemplate(connection);
// Query users with name = "mali"
UserInfo user = lambda.query(UserInfo.class)
.eq(UserInfo::getName, "mali")
.queryForObject();
// Update operation
lambda.update(UserInfo.class)
.eq(UserInfo::getId, user.getId())
.updateTo(UserInfo::getAge, 27)
.doUpdate();
2.5 Using XML to Manage Mapper (MyBatis Style)
For complex queries or scenarios where unified management of SQL is needed, dbVisitor supports using XML files to define Mappers, which is almost identical to the MyBatis experience.
Mapper Interface:
@RefMapper("mapper/user-mapper.xml")
public interface UserInfoXmlMapper {
int saveUser(@Param("info") UserInfo info);
List<UserInfo> listByUserName(@Param("userName") String userName, Page page);
}
XML File (user-mapper.xml):
<?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="com.example.mapper.UserInfoXmlMapper">
<resultMap id="userResultMap" type="com.example.entity.UserInfo">
<result column="_id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
</resultMap>
<insert id="saveUser">
test.user_info.insert({
name: #{info.name},
age: #{info.age}
})
</insert>
<!-- Supports automatic pagination -->
<select id="listByUserName" resultMap="userResultMap">
test.user_info.find({name: #{userName}})
</select>
</mapper>
3. Unified Pagination Implementation
In dbVisitor, whether operating on MySQL or MongoDB, the implementation of pagination queries is completely unified. You only need to pass a Page object.
// Create Page object
Page page = new PageObject();
page.setPageSize(10);
page.setPageNumber(0); // First page
// Execute query, dbVisitor will automatically intercept and rewrite it as a pagination query
// For MongoDB, it will automatically convert to .skip(0).limit(10)
List<UserInfo> list = mapper.listByUserName("mali", page);
// Get total record count (if needed)
long total = page.getTotalCount();
// Next page
page.nextPage();
list = mapper.listByUserName("mali", page);
4. Conclusion
With dbVisitor, we can operate both relational databases and MongoDB in the same project using the same set of APIs and the same mindset (Mapper/XML/Lambda). This greatly reduces the development and maintenance costs of hybrid architecture projects, making the data access layer cleaner and more unified.
If you are looking for a tool that can unify the RDBMS and NoSQL development experience, dbVisitor is definitely worth a try.