MongoDB 作為流行的 NoSQL 數據庫,與 Java 的整合是後端開發必備技能。本文通過完整示例演示 Java 驅動程式的核心操作,涵蓋連接管理、文檔增刪改查、條件查詢及數組類型處理。
現代項目建議使用 Maven 管理依賴,最新驅動包坐標:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.11.0</version> <!-- 請檢查最新版本 -->
</dependency>
import com.mongodb.client.*;
import org.bson.Document;
import java.util.Arrays;
public class MongoDBDemo {
public static void main(String[] args) {
// 連接 MongoDB(默認端口 27017)
try (MongoClient mongoClient = MongoClients.create("mongodb://172.27.9.104:27017")) {
MongoDatabase database = mongoClient.getDatabase("mytestdb");
MongoCollection collection = database.getCollection("mytestcoll");
// 清空集合以便演示
collection.drop();
// 插入單個文檔
Document doc = new Document("from", "blog.ithomer.net")
.append("to", "forum.ithomer.net")
.append("subject", "ithomer.net");
collection.insertOne(doc);
System.out.println("插入文檔 ID: " + doc.getObjectId("_id"));
// 批量插入
collection.insertMany(Arrays.asList(
new Document("ranking", 0),
new Document("ranking", 1),
new Document("ranking", 2)
));
System.out.println("集合文檔總數: " + collection.countDocuments());
}
}
}
// 查詢所有文檔
FindIterable allDocs = collection.find();
for (Document d : allDocs) {
System.out.println(d.toJson());
}
// 條件查詢:ranking = 1
Document queryEq = new Document("ranking", 1);
collection.find(queryEq).forEach(d -> System.out.println(d.toJson()));
// 範圍查詢:5 <= ranking < 9
Document queryRange = new Document("ranking",
new Document("$gte", 5).append("$lt", 9));
collection.find(queryRange).forEach(d -> System.out.println(d.toJson()));
// 投影查詢:只返回特定字段
collection.find().projection(new Document("ranking", 1).append("_id", 0))
.forEach(d -> System.out.println(d.toJson()));
// 排序與分頁
collection.find()
.sort(new Document("ranking", -1)) // 降序
.skip(0).limit(5) // 分頁
.forEach(d -> System.out.println(d.toJson()));
MongoDB 文檔常包含數組類型字段,以下示範如何讀取並映射到 Java 實體類:
public class MediaEntity {
private Long id;
private List tags = new ArrayList<>();
private List keywords = new ArrayList<>();
private List copyrights = new ArrayList<>();
private List actors = new ArrayList<>();
private List directors = new ArrayList<>();
// getter/setter 略
}
public class Actor {
private String name;
private Integer actorId;
// getter/setter 略
}
public static void loadMediaTags(List mediaEntityList) {
try (MongoClient mongoClient = MongoClients.create("mongodb://host:port")) {
MongoDatabase db = mongoClient.getDatabase("media_db");
MongoCollection collection = db.getCollection("media_coll");
// 查詢並逐個處理
for (Document doc : collection.find().limit(100)) {
MediaEntity entity = new MediaEntity();
entity.setId(doc.getLong("_id"));
// 處理簡單字符串數組
List tagList = doc.getList("tag", String.class);
if (tagList != null) {
tagList.forEach(tag -> {
entity.getTags().add(tag);
entity.getTagIds().add(getTagInt(tag)); // 查詢映射表
});
}
// 處理嵌套文檔數組
List actorsList = doc.getList("actors", Document.class);
if (actorsList != null) {
for (Document actorDoc : actorsList) {
String name = actorDoc.getString("name");
entity.getActors().add(new Actor(name, getActorInt(name)));
}
}
// 同理處理 director、keyword、copyright 等字段...
mediaEntityList.add(entity);
}
}
}
// 映射表查詢輔助方法(建議緩存優化)
private static int getTagInt(String tag) {
try (MongoClient client = MongoClients.create("mongodb://host:port")) {
Document result = client.getDatabase("db")
.getCollection("recommend_tag_map")
.find(new Document("name", tag))
.first();
return result != null ? result.getInteger("id", -1) : -1;
}
}
生產環境務必配置連接池,避免頻繁創建銷毀連接:
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString("mongodb://host:port"))
.applyToConnectionPoolSettings(builder ->
builder.maxSize(100).minSize(10))
.build();
try (MongoClient client = MongoClients.create(settings)) {
// 業務邏輯
}
// 為常用查詢字段創建索引
collection.createIndex(new Document("ranking", 1));
collection.createIndex(new Document("tag", 1)); // 數組字段也可建索引
List> writes = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
writes.add(new InsertOneModel<>(new Document("batch", i)));
}
collection.bulkWrite(writes, new BulkWriteOptions().ordered(false));
| 問題 | 解決方案 |
|---|---|
| 游標未關閉導致內存洩漏 | 使用 try-with-resources 或顯式調用 cursor.close() |
| 大量數據一次性加載 OOM | 使用 limit/skip 分頁,或批量處理配合游標 |
| 類型轉換異常 | 使用 Document.getList(key, Class) 安全獲取泛型集合 |
| 連接數耗盡 | 配置合理連接池,確保客戶端單例複用 |
Java 操作 MongoDB 核心在於理解 Document 模型與 BSON 類型映射。掌握基本 CRUD、條件查詢操作符($gte, $lt, $in 等)、數組嵌套文檔處理,並遵循連接池複用、索引優化、批量寫入等最佳實踐,即可構建高性能、穩定的數據訪問層。