杰瑞科技汇

java mongodb 对象

  1. 核心概念:驱动、BSON 与 POJO
  2. 环境搭建
  3. 核心操作:增删改查
  4. 高级特性:对象映射
  5. 最佳实践与注意事项

核心概念

a. MongoDB Java Driver

这是官方提供的 Java 库,是 Java 应用与 MongoDB 数据库通信的桥梁,它负责:

java mongodb 对象-图1
(图片来源网络,侵删)
  • 建立与管理数据库连接。
  • 将 Java 对象序列化为 BSON 格式(发送给 MongoDB)。
  • 将 BSON 格式反序列化为 Java 对象(从 MongoDB 读取)。

b. BSON (Binary JSON)

MongoDB 存储的数据格式是 BSON,它是一种二进制表示的 JSON,类似于 JSON,但支持更多的数据类型(如 Date, ObjectId, Binary 等),驱动程序会自动帮你处理 Java 类型与 BSON 类型之间的转换。

c. POJO (Plain Old Java Object)

就是我们平常创建的普通 Java 类,UserProduct 等,为了让驱动程序知道如何将一个 BSON 文档映射成一个 Java 对象,我们需要遵循一些约定。

一个典型的 POJO 示例:

// 文档集合: users
public class User {
    // MongoDB 文档中的 _id 字段会自动映射到这里
    // POJO 中没有 id 字段,驱动会自动创建一个
    private String id;
    // 字段名会与 JSON Key 对应
    private String name;
    private int age;
    private String email;
    private List<String> roles; // 对应数组类型
    private Date createdAt;    // 对应日期类型
    // 必须提供一个无参构造函数,用于反序列化
    public User() {
    }
    // 推荐提供一个全参构造函数,方便创建对象
    public User(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
        this.createdAt = new Date();
    }
    // Getters and Setters (必须)
    public String getId() { return id; }
    public void setId(String 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 String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public List<String> getRoles() { return roles; }
    public void setRoles(List<String> roles) { this.roles = roles; }
    public Date getCreatedAt() { return createdAt; }
    public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; }
    // (可选) 重写 toString() 方便打印日志
    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", email='" + email + '\'' +
                ", roles=" + roles +
                ", createdAt=" + createdAt +
                '}';
    }
}

环境搭建

使用 Maven 是最简单的方式,在你的 pom.xml 文件中添加最新的 MongoDB Java Driver 依赖。

java mongodb 对象-图2
(图片来源网络,侵删)
<dependencies>
    <!-- MongoDB Java Driver -->
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver-sync</artifactId>
        <version>4.11.1</version> <!-- 请使用最新版本 -->
    </dependency>
    <!-- (可选) 用于 JSON 操作,方便调试 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.2</version>
    </dependency>
</dependencies>

核心操作:增删改查

a. 连接数据库

你需要创建一个 MongoClient 来连接 MongoDB 服务器。

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoCollection;
public class MongoConnectionExample {
    public static void main(String[] args) {
        // 连接字符串,格式为 "mongodb://host:port"
        String connectionString = "mongodb://localhost:27017";
        try (MongoClient mongoClient = MongoClients.create(connectionString)) {
            // 获取数据库,如果数据库不存在,MongoDB 会在第一次写入时自动创建
            MongoDatabase database = mongoClient.getDatabase("myDatabase");
            System.out.println("成功连接到数据库: " + database.getName());
            // 获取集合 (Collection),类似于关系数据库中的表
            MongoCollection<User> collection = database.getCollection("users", User.class);
            System.out.println("成功获取集合: users");
            // 后续的增删改查操作都基于这个 collection 对象
            // insertExample(collection);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // ... 其他方法
}

b. 插入数据

使用 insertOne() 插入单个文档。

import static com.mongodb.client.model.Filters.eq; // 后面会用到
public static void insertExample(MongoCollection<User> collection) {
    // 1. 创建 Java 对象
    User newUser = new User("Alice", 30, "alice@example.com");
    newUser.setRoles(Arrays.asList("user", "editor"));
    // 2. 插入对象
    collection.insertOne(newUser);
    System.out.println("成功插入用户: " + newUser);
    // 插入多个
    // List<User> users = Arrays.asList(...);
    // collection.insertMany(users);
}

c. 查询数据

查询是 MongoDB 最强大的功能之一。

import static com.mongodb.client.model.Filters.*;
import static com.mongodb.client.model.Projections.*;
import com.mongodb.client.model.FindOneAndUpdateOptions;
public static void findExample(MongoCollection<User> collection) {
    // 1. 查找单个文档
    // 假设我们刚刚插入了 Alice,现在通过 name 查找
    User foundUser = collection.find(eq("name", "Alice")).first();
    System.out.println("查找到单个用户: " + foundUser);
    // 2. 查找所有文档
    System.out.println("\n--- 所有用户 ---");
    collection.find().forEach(doc -> System.out.println(doc));
    // 3. 条件查询
    System.out.println("\n--- 年龄大于25的用户 ---");
    collection.find(gt("age", 25)).forEach(doc -> System.out.println(doc));
    // 4. 复杂查询 (AND, OR)
    System.out.println("\n--- 名为Alice且年龄为30的用户 ---");
    collection.find(and(eq("name", "Alice"), eq("age", 30))).forEach(doc -> System.out.println(doc));
    // 5. 投影 - 只返回需要的字段
    System.out.println("\n--- 只返回name和age字段 ---");
    collection.find().projection(fields(include("name", "age"), excludeId())).forEach(doc -> System.out.println(doc));
}

d. 更新数据

更新操作可以使用 updateOneupdateMany

public static void updateExample(MongoCollection<User> collection) {
    // 1. 更新一个文档
    // 将 name 为 "Alice" 的用户的年龄更新为 31
    collection.updateOne(
        eq("name", "Alice"), // 过滤条件
        new Document("$set", new Document("age", 31)) // 更新操作
    );
    System.out.println("将 Alice 的年龄更新为 31");
    // 2. 使用更现代的 Updates 类
    import com.mongodb.client.model.Updates;
    collection.updateOne(
        eq("name", "Alice"),
        Updates.set("email", "alice.new@example.com")
    );
    System.out.println("将 Alice 的邮箱更新");
    // 3. 查找并更新 (原子操作)
    // 如果不存在,则插入一个新文档
    User updatedUser = collection.findOneAndUpdate(
        eq("name", "Bob"), // 查找条件
        Updates.set("age", 40), // 更新操作
        new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER) // 返回更新后的文档
    );
    System.out.println("查找并更新 Bob: " + updatedUser);
}

e. 删除数据

删除操作可以使用 deleteOnedeleteMany

public static void deleteExample(MongoCollection<User> collection) {
    // 1. 删除一个文档
    // 删除 name 为 "Alice" 的用户
    DeleteResult deleteResult = collection.deleteOne(eq("name", "Alice"));
    System.out.println("删除了 " + deleteResult.getDeletedCount() + " 个名为 Alice 的用户");
    // 2. 删除多个文档
    // 删除所有年龄小于 25 的用户
    deleteResult = collection.deleteMany(lt("age", 25));
    System.out.println("删除了 " + deleteResult.getDeletedCount() + " 个年龄小于 25 的用户");
}

高级特性:对象映射

上面的例子已经使用了最简单的映射方式,驱动程序提供了更强大的注解功能,让你可以精确控制字段映射。

a. @BsonProperty 注解

当 Java 字段名与文档中的 Key 不一致时使用。

public class Product {
    private String productId; // 对应文档中的 "product_id"
    private String productName;
    // 使用注解指定映射的 BSON 字段名
    @BsonProperty("product_id")
    public String getProductId() {
        return productId;
    }
    public void setProductId(String productId) {
        this.productId = productId;
    }
    // ... 其他 getter/setter
}

b. @BsonId 注解

明确指定哪个字段作为文档的 _id_id 可以是任何类型,而不仅仅是 StringObjectId

import org.bson.types.ObjectId;
import org.bson.annotations.BsonId;
public class Article {
    // 使用 ObjectId 作为 _id
    @BsonId
    private ObjectId id;
    private String title;
    private String content;
    // getter/setter ...
    public ObjectId getId() { return id; }
    // ...
}

c. @BsonDiscriminator 注解

当你需要在同一个集合中存储不同类型的对象时(多态),这个注解非常有用。

// 定义一个公共接口
interface Shape {}
// 使用 @BsonDiscriminator 来区分类型
@BsonDiscriminator(value = "shape_type")
abstract class AbstractShape implements Shape {
    @BsonId
    private String id;
    // ...
}
class Circle extends AbstractShape {
    private double radius;
    // ...
}
class Rectangle extends AbstractShape {
    private double width;
    private double height;
    // ...
}

最佳实践与注意事项

  1. 连接管理

    • 最佳实践MongoClient 是一个重量级对象,应该在整个应用生命周期中只创建一次,推荐使用依赖注入(如 Spring 的 @Bean)或单例模式来管理它。
    • try-with-resources 语句 (try (MongoClient client = ...)) 适用于短生命周期的脚本或测试,因为它会在块结束时关闭连接。
  2. 异常处理

    • 总是使用 try-catch 块来捕获 MongoException 或其子类,以处理网络问题、服务器错误等。
  3. 索引

    • 对于频繁查询的字段(如 name, email),一定要创建索引,可以极大地提升查询性能。
      // 为 name 字段创建升序索引
      collection.createIndex(Indexes.ascending("name"));
  4. 批量操作

    • 当需要插入或更新大量数据时,优先使用 insertMany()bulkWrite() 等批量操作,它们比循环执行单次操作效率高得多。
  5. 使用 FiltersUpdates

    • 优先使用驱动提供的 FiltersUpdates 工具类来构建查询和更新条件,而不是手动拼接 Document,这样代码更清晰、更安全,并且能利用编译器检查。

在 Java 中使用 MongoDB 的核心流程就是:

  1. 定义 POJO:创建与 MongoDB 文档结构对应的 Java 类。
  2. 获取 MongoCollection:通过 MongoClient 连接到数据库,并获取操作特定集合的 MongoCollection<T> 对象,T 就是你的 POJO 类型。
  3. 调用方法:使用 collection.find(), collection.insertOne(), collection.updateOne() 等方法进行数据操作,驱动会自动完成对象与 BSON 的转换。

希望这份详细的指南能帮助你理解和使用 Java 操作 MongoDB 对象!

分享:
扫描分享到社交APP
上一篇
下一篇