MongoDB 官方提供了一个强大的 Java 驱动程序,它提供了两种主要的操作方式:

- MongoDB Java Driver (原生 API):直接使用驱动提供的
MongoCollection,Filters,Projections等类来构建查询和操作,这是最底层、最灵活的方式。 - Spring Data MongoDB:在原生驱动之上构建,提供了类似 Spring Data JPA 的编程模型,如
Repository接口,极大地简化了数据访问层的代码,这是目前企业级应用中最主流的方式。
下面我将分别介绍这两种方式,并提供一个完整的、可运行的示例。
核心概念:Bson vs. POJO
在深入代码之前,必须理解两个关键概念:
- BSON (Binary JSON):MongoDB 存储的数据格式,在 Java 驱动中,它被表示为
org.bson.Document或其他实现了Bson接口的类,你可以把它看作一个通用的、键值对的集合,类似于Map<String, Object>。 - POJO (Plain Old Java Object):普通的 Java 对象,也就是我们业务逻辑中常用的实体类,如
User,Product等。
MongoDB 驱动需要在 Bson 和 POJO 之间进行转换。
- 序列化:将 POJO 转换为 BSON (存入数据库)。
- 反序列化:将 BSON 转换为 POJO (从数据库读取)。
驱动程序会使用反射机制,通过 POJO 的字段名和 BSON 的键名进行匹配。

使用原生 MongoDB Java Driver
这种方式让你完全控制查询的构建过程,适合学习底层原理或需要编写复杂、高性能查询的场景。
准备工作:添加依赖
如果你使用 Maven,在 pom.xml 中添加依赖:
<dependencies>
<!-- MongoDB Java Driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.11.1</version> <!-- 请使用最新版本 -->
</dependency>
<!-- 为了方便打印 JSON,可以添加这个 -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>bson</artifactId>
<version>4.11.1</version>
</dependency>
</dependencies>
创建 POJO 类
创建一个与 MongoDB 集合对应的 Java 类。
// src/main/java/com/example/User.java
package com.example;
import org.bson.types.ObjectId;
import java.util.Date;
// @Document 注解在原生驱动中不是必须的,但有助于代码清晰
public class User {
// 使用 ObjectId 作为主键,对应 MongoDB 的 _id
private ObjectId id;
private String name;
private int age;
private Date registrationDate;
private String[] hobbies; // 数组类型
// 无参构造函数是反序列化所必需的
public User() {}
// 全参构造函数 (可选,但推荐)
public User(String name, int age, Date registrationDate, String[] hobbies) {
this.name = name;
this.age = age;
this.registrationDate = registrationDate;
this.hobbies = hobbies;
}
// Getters and Setters
public ObjectId getId() { return id; }
public void setId(ObjectId id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Date getRegistrationDate() { return registrationDate; }
public void setRegistrationDate(Date registrationDate) { this.registrationDate = registrationDate; }
public String[] getHobbies() { return hobbies; }
public void setHobbies(String[] hobbies) { this.hobbies = hobbies; }
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", registrationDate=" + registrationDate +
", hobbies=" + String.join(", ", hobbies) +
'}';
}
}
编写代码进行 CRUD 操作
// src/main/java/com/example/MongoNativeExample.java
package com.example;
import com.mongodb.client.*;
import com.mongodb.client.model.*;
import org.bson.Document;
import org.bson.types.ObjectId;
import java.util.Arrays;
import java.util.Date;
public class MongoNativeExample {
public static void main(String[] args) {
// 1. 创建 MongoClient,连接到本地 MongoDB 服务
String uri = "mongodb://localhost:27017";
try (MongoClient mongoClient = MongoClients.create(uri)) {
// 2. 获取数据库,如果不存在会自动创建
MongoDatabase database = mongoClient.getDatabase("testdb");
// 3. 获取集合,如果不存在会自动创建
MongoCollection<Document> collection = database.getCollection("users");
// --- 插入单个文档 ---
System.out.println("--- 插入单个文档 ---");
User newUser = new User("Alice", 30, new Date(), new String[]{"Reading", "Hiking"});
// 将 POJO 转换为 Document
Document docToInsert = Document.parse(com.mongodb.client.model.Converters.toDocument(newUser));
collection.insertOne(docToInsert);
System.out.println("插入成功: " + docToInsert.toJson());
// --- 插入多个文档 ---
System.out.println("\n--- 插入多个文档 ---");
User user2 = new User("Bob", 25, new Date(), new String[]{"Gaming", "Cooking"});
User user3 = new User("Charlie", 35, new Date(), new String[]{"Coding", "Swimming"});
collection.insertMany(Arrays.asList(
Document.parse(com.mongodb.client.model.Converters.toDocument(user2)),
Document.parse(com.mongodb.client.model.Converters.toDocument(user3))
));
System.out.println("批量插入成功");
// --- 查询所有文档 ---
System.out.println("\n--- 查询所有文档 ---");
// FindIterable<Document> 是惰性的,只有迭代时才会执行查询
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> cursor = findIterable.iterator();
try {
while (cursor.hasNext()) {
System.out.println(cursor.next().toJson());
}
} finally {
cursor.close(); // 必须关闭 cursor
}
// --- 查询特定文档 (使用 Filters) ---
System.out.println("\n--- 查询名为 'Alice' 的用户 ---");
// 将查询结果直接映射为 User 对象列表
FindIterable<User> findIterableUser = collection.find(Filters.eq("name", "Alice"), User.class);
MongoCursor<User> userCursor = findIterableUser.iterator();
try {
while (userCursor.hasNext()) {
System.out.println("查询结果 (POJO): " + userCursor.next());
}
} finally {
userCursor.close();
}
// --- 更新文档 ---
System.out.println("\n--- 更新 Bob 的年龄 ---");
// 更新第一个匹配的文档
collection.updateOne(
Filters.eq("name", "Bob"),
Updates.set("age", 26)
);
System.out.println("更新成功");
// --- 删除文档 ---
System.out.println("\n--- 删除名为 Charlie 的用户 ---");
DeleteResult deleteResult = collection.deleteOne(Filters.eq("name", "Charlie"));
System.out.println("删除了 " + deleteResult.getDeletedCount() + " 个文档");
// --- 清理集合 (可选) ---
// collection.drop(); // 删除整个集合
}
}
}
使用 Spring Data MongoDB (推荐)
这是更现代、更简洁的方式,尤其适合构建 Spring Boot 应用。
准备工作:添加依赖
在 Spring Boot 项目的 pom.xml 中,通常只需要一个 spring-boot-starter-data-mongodb 依赖即可。
<dependencies>
<!-- Spring Boot Starter for MongoDB -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置连接
在 application.properties 或 application.yml 中配置 MongoDB 连接信息。
application.properties:
spring.data.mongodb.uri=mongodb://localhost:27017/testdb
application.yml:
spring:
data:
mongodb:
uri: mongodb://localhost:27017/testdb
创建 POJO 类 (与原生驱动相同)
这个 User.java 类和上面的一模一样。
创建 Repository 接口
这是 Spring Data 的核心,你只需要定义一个接口,继承 MongoRepository,Spring Data 会自动为你实现所有 CRUD 方法。
// src/main/java/com/example/UserRepository.java
package com.example;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserRepository extends MongoRepository<User, String> {
// Spring Data 会根据方法名自动生成查询
// 查询所有年龄大于指定值的用户
List<User> findByAgeGreaterThan(int age);
// 查询名字为指定值的用户
User findByName(String name);
}
MongoRepository<T, ID>:T是实体类型 (User),ID是主键类型 (String,因为ObjectId可以被当作String处理)。- 方法名解析:
findBy...是约定,GreaterThan是查询条件。
创建 Service 和 Controller 来使用 Repository
// src/main/java/com/example/UserService.java
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User saveUser(User user) {
return userRepository.save(user);
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
public User getUserByName(String name) {
return userRepository.findByName(name);
}
public List<User> getUsersOlderThan(int age) {
return userRepository.findByAgeGreaterThan(age);
}
public void deleteUser(String id) {
userRepository.deleteById(id);
}
}
创建一个简单的应用类来测试
// src/main/java/com/example/MongoSpringApplication.java
package com.example;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@SpringBootApplication
public class MongoSpringApplication {
public static void main(String[] args) {
SpringApplication.run(MongoSpringApplication.class, args);
}
// CommandLineRunner 会在应用启动后自动执行
@Bean
public CommandLineRunner run(UserRepository repository, MongoTemplate mongoTemplate) {
return args -> {
System.out.println("--- Spring Data MongoDB 示例开始 ---");
// 使用 MongoTemplate 进行更复杂的查询 (可选)
// mongoTemplate.insert(new User("David", 40, new Date(), new String[]{"Fishing"}), "users");
// 1. 保存
System.out.println("\n1. 保存用户...");
User user1 = repository.save(new User("Eve", 28, new Date(), new String[]{"Painting", "Dancing"}));
User user2 = repository.save(new User("Frank", 45, new Date(), new String[]{"Gardening"}));
System.out.println("保存成功: " + user1.getName() + ", " + user2.getName());
// 2. 查询所有
System.out.println("\n2. 查询所有用户...");
List<User> allUsers = repository.findAll();
allUsers.forEach(System.out::println);
// 3. 使用自定义方法查询
System.out.println("\n3. 查询年龄大于 30 的用户...");
List<User> olderUsers = repository.findByAgeGreaterThan(30);
olderUsers.forEach(System.out::println);
// 4. 根据名字查询
System.out.println("\n4. 根据 'Eve' 查询用户...");
User foundUser = repository.findByName("Eve");
System.out.println("找到用户: " + foundUser);
// 5. 删除
System.out.println("\n5. 删除用户 'Frank'...");
repository.deleteById(user2.getId());
System.out.println("删除成功");
System.out.println("剩余用户: " + repository.findAll().size());
};
}
}
总结与对比
| 特性 | 原生 Java Driver | Spring Data MongoDB |
|---|---|---|
| 易用性 | 较低,需要手动构建查询和转换对象 | 非常高,通过接口和约定简化大量代码 |
| 灵活性 | 极高,可以构建任何复杂的查询和命令 | 较高,但受限于 Repository 接口和 MongoTemplate 的能力 |
| 学习曲线 | 陡峭,需要理解 MongoDB 的底层 API | 平缓,尤其对 Spring 框架熟悉的开发者 |
| 适用场景 | 学习、性能关键型应用、复杂查询脚本 | 绝大多数企业级应用、快速开发、微服务 |
| 依赖 | mongodb-driver-sync |
spring-boot-starter-data-mongodb |
建议:
- 新手或快速开发:直接使用 Spring Data MongoDB,它能让你专注于业务逻辑,而不是数据库连接和查询细节。
- 深入理解或特殊需求:从 原生驱动 开始学习,了解其工作原理,当你需要编写无法通过
Repository实现的复杂查询时,可以在 Spring 项目中注入MongoTemplate来使用原生驱动的功能。
