Trang chủHướng dẫnHướng dẫn thao tác CRUD MongoDB bằng Java [chi tiết từ A đến Z]
Java

Hướng dẫn thao tác CRUD MongoDB bằng Java [chi tiết từ A đến Z]

CyStack blog 6 phút để đọc
CyStack blog20/08/2025
Locker Avatar

Bao Tran

Web Developer

Locker logo social
Reading Time: 6 minutes

Trước đây, chúng ta đã cùng nhau tìm hiểu cách cài đặt MongoDB trên các hệ điều hành Unix và thực thi một số lệnh cơ bản từ terminal. Hôm nay, tôi sẽ cùng các bạn đi sâu vào MongoDB Java Driver, khám phá các tính năng của nó và hướng dẫn thao tác CRUD MongoDB bằng Java.

Việc nắm vững cách tương tác giữa Java và MongoDB là một kỹ năng thiết yếu cho bất kỳ lập trình viên Java nào muốn xây dựng các ứng dụng hiện đại, có khả năng mở rộng.

CRUD MongoDB bằng Java

Tải và cài đặt MongoDB Driver

Nếu bạn đang sử dụng Maven project, chỉ cần thêm dependency sau vào file pom.xml của ứng dụng để bao gồm MongoDB Java Driver:

<dependency>
	<groupId>org.mongodb</groupId>
	<artifactId>mongo-java-driver</artifactId>
	<version>2.12.3</version>
</dependency>

Đối với standalone project, bạn có thể tải MongoDB Java Driver từ link này và thêm nó vào build path của project.

Bây giờ, hãy cùng đi sâu vào cách sử dụng cơ bản của MongoDB Java Driver trước khi chúng ta xem xét một chương trình ví dụ hoàn chỉnh về các thao tác CRUD.

Tạo kết nối MongoDB từ Java

MongoClient đóng vai trò là giao diện chính kết nối chương trình Java của chúng ta với MongoDB server. Chúng ta sử dụng MongoClient để thiết lập kết nối, tương tác với cơ sở dữ liệu, truy xuất tên các collection, và thực hiện các thao tác tạo/đọc/cập nhật/xóa (CRUD) trên cơ sở dữ liệu, collections và document.

Một trong những tính năng tôi đặc biệt yêu thích ở MongoDB Java Driver là khả năng thread-safe. Điều này có nghĩa là chúng ta chỉ cần tạo một instance của MongoClient duy nhất và có thể tái sử dụng nó một cách an toàn trên nhiều thread khác nhau. Ngay cả khi nhiều thread cùng lúc truy cập MongoClient, hệ thống sẽ trả về một kết nối từ pool kết nối nội bộ mà nó duy trì. Đối với mỗi yêu cầu gửi đến cơ sở dữ liệu (như find, insert…), thread Java sẽ lấy một kết nối từ pool, thực thi thao tác và sau đó giải phóng kết nối đó. Điều này có nghĩa là kết nối (socket) được sử dụng có thể khác nhau mỗi lần.

Dưới đây là một số phương thức phổ biến để kết nối đến MongoDB server:

MongoClient mongoClient = new MongoClient(); // kết nối đến host và port mặc định: 127.0.0.1:27017
// hoặc
MongoClient mongoClient = new MongoClient( "localhost" ); // kết nối đến port mặc định: 27017
// hoặc
MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // nên sử dụng cách này để tường minh

// hoặc, để kết nối đến một replica set, với khả năng tự động khám phá primary
MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("localhost", 27017),
                                      new ServerAddress("localhost", 27018),
                                      new ServerAddress("localhost", 27019)));

Kết nối đến cơ sở dữ liệu MongoDB

Sau khi chúng ta thiết lập kết nối đến MongoDB server, bước tiếp theo là tạo kết nối đến một cơ sở dữ liệu cụ thể, như ví dụ dưới đây. Lưu ý rằng, nếu cơ sở dữ liệu chưa tồn tại, MongoDB sẽ tự động tạo mới cho bạn.

MongoClient mongo = new MongoClient("localhost", 27017);
DB db = mongo.getDB("journaldev");

MongoClient còn cung cấp một phương thức hữu ích để lấy tất cả các tên cơ sở dữ liệu hiện có, như ví dụ sau:

MongoClient mongo = new MongoClient("localhost", 27017);
List<String> dbs = mongo.getDatabaseNames();
System.out.println(dbs); // Output có thể là: [journaldev, local, admin]

Chúng ta cũng có thể cấu hình xác thực dựa trên tên người dùng và mật khẩu cho các cơ sở dữ liệu. Trong trường hợp đó, chúng ta cần cung cấp thông tin xác thực như sau:

MongoCredential journaldevAuth = MongoCredential.createPlainCredential("pankaj", "journaldev", "pankaj123".toCharArray());
MongoCredential testAuth = MongoCredential.createPlainCredential("pankaj", "test", "pankaj123".toCharArray());
List<MongoCredential> auths = new ArrayList<MongoCredential>();
auths.add(journaldevAuth);
auths.add(testAuth);

ServerAddress serverAddress = new ServerAddress("localhost", 27017);
MongoClient mongo = new MongoClient(serverAddress, auths);

Nếu bạn đang sử dụng các phiên bản cũ hơn của driver, bạn có thể cần cung cấp thông tin xác thực sau khi đã lấy được đối tượng cơ sở dữ liệu, như ví dụ dưới đây:

MongoClient mongo = new MongoClient("localhost", 27017);
DB db = mongo.getDB("journaldev");
boolean auth = db.authenticate("pankaj", "pankaj123".toCharArray());

Bạn có thể dễ dàng nhận ra nhược điểm của cách tiếp cận cũ: việc xác thực nên được thực hiện ngay từ giai đoạn đầu vì chúng ta khó có thể phục hồi nếu xảy ra lỗi sau đó.

Chúng ta có thể xóa một cơ sở dữ liệu bằng cách sử dụng phương thức dropDatabase(String db) của MongoClient hoặc phương thức dropDatabase() của DB. Vì thao tác này tác động đến toàn bộ cơ sở dữ liệu, tôi ưu tiên sử dụng phương thức của MongoClient để đảm bảo tính rõ ràng.

MongoDB và Collections

Mỗi cơ sở dữ liệu có thể chứa không hoặc nhiều collections. Chúng giống như các bảng trong cơ sở dữ liệu quan hệ, nhưng điểm khác biệt lớn nhất là chúng không yêu cầu một định dạng dữ liệu cụ thể (schema-less). Hãy hình dung nó như sự khác biệt giữa một List chung chung và một List<String> trong ngôn ngữ lập trình Java.

Chúng ta có thể lấy tất cả các tên collection bằng đoạn code sau:

MongoClient mongo = new MongoClient("localhost", 27017);
DB db = mongo.getDB("journaldev");

Set<String> collections = db.getCollectionNames();
System.out.println(collections); // Output có thể là: [datas, names, system.indexes, users]

Chúng ta có thể lấy một collection cụ thể bằng cách cung cấp tên của nó, như ví dụ dưới đây:

DB db = mongo.getDB("journaldev");
DBCollection col = db.getCollection("users");

Tương tự như cơ sở dữ liệu, nếu collection chưa tồn tại, MongoDB sẽ tự động tạo mới khi bạn gọi db.getCollection("tên_collection"). Tất cả dữ liệu trong MongoDB đều được lưu trữ trong một collection nào đó. Tại thời điểm này, chúng ta đã sẵn sàng thực hiện các thao tác insert/update/delete.

Chúng ta có thể sử dụng phương thức drop() của DBCollection để xóa một collection khỏi cơ sở dữ liệu.

Ví dụ Java với MongoDB

Mặc dù chúng ta có thể làm việc với bất kỳ document JSON hợp lệ nào trong MongoDB collection, nhưng trong thực tế, chúng ta thường có các lớp POJO (Plain Old Java Object) được ánh xạ với các dữ liệu này. Vì vậy, tôi sẽ tạo một Java bean và sử dụng nó cho các ví dụ của mình.

User.java

package com.journaldev.mongodb.model;

public class User {

	private int id;
	private String name;
	private String role;
	private boolean isEmployee;

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	public boolean isEmployee() {
		return isEmployee;
	}
	public void setEmployee(boolean isEmployee) {
		this.isEmployee = isEmployee;
	}
}

Đây là chương trình ví dụ hoàn chỉnh về MongoDB Java, minh họa từng thao tác CRUD một cách tuần tự.

MongoDBExample.java

package com.journaldev.mongodb.main;

import java.net.UnknownHostException;

import com.journaldev.mongodb.model.User;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.WriteResult;

public class MongoDBExample {

	public static void main(String[] args) throws UnknownHostException {

		User user = createUser();
		DBObject doc = createDBObject(user);

		MongoClient mongo = new MongoClient("localhost", 27017);
		DB db = mongo.getDB("journaldev");

		DBCollection col = db.getCollection("users");

		// Tạo người dùng (Create operation)
		WriteResult result = col.insert(doc);
		System.out.println(result.getUpsertedId());
		System.out.println(result.getN());
		System.out.println(result.isUpdateOfExisting());
		System.out.println(result.getLastConcern());

		// Đọc người dùng (Read operation)
		DBObject query = BasicDBObjectBuilder.start().add("_id", user.getId()).get();
		DBCursor cursor = col.find(query);
		while(cursor.hasNext()){
			System.out.println(cursor.next());
		}

		// Cập nhật người dùng (Update operation)
		user.setName("Pankaj Kumar");
		doc = createDBObject(user);
		result = col.update(query, doc);
		System.out.println(result.getUpsertedId());
		System.out.println(result.getN());
		System.out.println(result.isUpdateOfExisting());
		System.out.println(result.getLastConcern());

		// Xóa người dùng (Delete operation)
		result = col.remove(query);
		System.out.println(result.getUpsertedId());
		System.out.println(result.getN());
		System.out.println(result.isUpdateOfExisting());
		System.out.println(result.getLastConcern());

		// Đóng tài nguyên
		mongo.close();
	}

	private static DBObject createDBObject(User user) {
		BasicDBObjectBuilder docBuilder = BasicDBObjectBuilder.start();

		docBuilder.append("_id", user.getId());
		docBuilder.append("name", user.getName());
		docBuilder.append("role", user.getRole());
		docBuilder.append("isEmployee", user.isEmployee());
		return docBuilder.get();
	}

	private static User createUser() {
		User u = new User();
		u.setId(2);
		u.setName("Pankaj");
		u.setEmployee(true);
		u.setRole("CEO");
		return u;
	}
}

Một kết quả thực thi mẫu sẽ cho ra output sau:

null
0
false
WriteConcern { "getlasterror" : 1} / (Continue on error? false)
{ "_id" : 2 , "name" : "Pankaj" , "role" : "CEO" , "isEmployee" : true}
null
1
true
WriteConcern { "getlasterror" : 1} / (Continue on error? false)
null
1
false
WriteConcern { "getlasterror" : 1} / (Continue on error? false)

Lưu ý rằng tôi lưu id của User với tên là _id. Đây là một khóa dành riêng, đóng vai trò như khóa chính cho bất kỳ bản ghi nào trong collection. Nếu chúng ta không cung cấp một _id, MongoDB sẽ tự động tạo một _id duy nhất cho chúng ta, tương tự như các cột tự tăng hoặc sequencer trong các bảng cơ sở dữ liệu quan hệ.

Vì tôi đang xóa bản ghi đã tạo, các lần thực thi tiếp theo sẽ không gây ra lỗi. Tuy nhiên, nếu có bản ghi trùng lặp, chúng ta sẽ nhận được lỗi dưới đây:

Exception in thread "main" com.mongodb.MongoException$DuplicateKey: { "serverUsed" : "localhost:27017" , "ok" : 1 , "n" : 0 ,
 "err" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: journaldev.users.$_id_  dup key: { : 1 }" ,
"code" : 11000}
	at com.mongodb.CommandResult.getWriteException(CommandResult.java:88)
	at com.mongodb.CommandResult.getException(CommandResult.java:79)
	at com.mongodb.DBCollectionImpl.translateBulkWriteException(DBCollectionImpl.java:314)
	at com.mongodb.DBCollectionImpl.insert(DBCollectionImpl.java:189)
	at com.mongodb.DBCollectionImpl.insert(DBCollectionImpl.java:165)
	at com.mongodb.DBCollection.insert(DBCollection.java:93)
	at com.mongodb.DBCollection.insert(DBCollection.java:78)
	at com.mongodb.DBCollection.insert(DBCollection.java:120)
	at com.journaldev.mongodb.main.MongoDBExample.main(MongoDBExample.java:27)

Kết luận

Chúng ta đã cùng nhau khám phá quy trình thiết lập MongoDB Java Driver, cách thiết lập kết nối, tương tác với cơ sở dữ liệu và collections, cũng như thực hiện các thao tác CRUD cơ bản nhất.

Những kiến thức này là nền tảng vững chắc giúp bạn xây dựng các ứng dụng Java mạnh mẽ và linh hoạt, tương tác hiệu quả với MongoDB dù là ứng dụng web, mobile backend, hay microservices. Khả năng thread-safe của MongoClient cũng giúp chúng ta tối ưu hiệu suất và quản lý tài nguyên kết nối một cách hiệu quả trong môi trường đa luồng.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất