杰瑞科技汇

mongodb java项目

  1. 环境准备:安装 MongoDB 和 Java 开发环境。
  2. 项目创建:使用 Maven 创建项目。
  3. 核心依赖:介绍并添加 MongoDB Java 驱动。
  4. 连接数据库:建立与 MongoDB 服务器的连接。
  5. CRUD 操作:创建、读取、更新、删除文档。
  6. 高级查询:条件查询、排序、分页。
  7. 索引:创建和使用索引以提高查询性能。
  8. 聚合框架:进行复杂的数据分析。
  9. 完整项目示例:一个包含所有上述功能的可运行示例。
  10. 最佳实践:连接池、异常处理、文档映射等。

环境准备

在开始之前,请确保你已经安装了以下软件:

mongodb java项目-图1
(图片来源网络,侵删)
  • Java Development Kit (JDK): 版本 8 或更高版本。
  • Apache Maven: 用于项目构建和依赖管理。
  • MongoDB Server: 可以是本地安装的,也可以是 MongoDB Atlas (云服务)。

验证安装: 打开终端或命令提示符,运行以下命令:

java -version
mvn -version
mongod --version # 如果是本地安装

项目创建 (使用 Maven)

我们将使用 Maven 来创建一个标准的 Java 项目。

  1. 创建项目目录

    mkdir mongodb-java-project
    cd mongodb-java-project
  2. 创建 Maven 项目结构

    mongodb java项目-图2
    (图片来源网络,侵删)
    mkdir -p src/main/java/com/example/mongodb
    mkdir -p src/main/resources
    mkdir -p src/test/java/com/example/mongodb
  3. 创建 pom.xml 文件: 在项目根目录下创建 pom.xml 文件,这是 Maven 项目的核心配置文件。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.example</groupId>
        <artifactId>mongodb-java-project</artifactId>
        <version>1.0-SNAPSHOT</version>
        <properties>
            <maven.compiler.source>11</maven.compiler.source>
            <maven.compiler.target>11</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <mongodb.driver.version>4.11.1</mongodb.driver.version>
        </properties>
        <dependencies>
            <!-- MongoDB Java Driver -->
            <dependency>
                <groupId>org.mongodb</groupId>
                <artifactId>mongodb-driver-sync</artifactId>
                <version>${mongodb.driver.version}</version>
            </dependency>
            <!-- For JSON-B (optional, for POJO mapping) -->
            <dependency>
                <groupId>javax.json</groupId>
                <artifactId>javax.json-api</artifactId>
                <version>1.1.4</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>11</source>
                        <target>11</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>

核心依赖

我们主要依赖 mongodb-driver-sync,这是 MongoDB 官方提供的同步 Java 驱动,适用于大多数标准 Java 应用程序。


连接数据库

在 Java 代码中,与 MongoDB 交互的第一步是建立连接,核心类是 MongoClient

MongoClientExample.java

package com.example.mongodb;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
public class MongoClientExample {
    public static void main(String[] args) {
        // MongoDB 连接字符串
        // 格式: mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
        String uri = "mongodb://localhost:27017"; // 连接到本地默认端口
        // 创建 MongoClient 实例
        // 从 MongoDB 4.0+ 开始,推荐使用 MongoClients.create(),它会自动管理连接池
        try (MongoClient mongoClient = MongoClients.create(uri)) {
            // 连接到指定的数据库
            // 如果数据库不存在,MongoDB 会在第一次插入数据时自动创建
            MongoDatabase database = mongoClient.getDatabase("mydb");
            System.out.println("成功连接到数据库: " + database.getName());
            // 获取集合 (Collection)
            // 集合类似于关系型数据库中的表
            // database.getCollection("myCollection"); // 这行代码只是获取集合对象,不会创建
        } catch (Exception e) {
            System.err.println("连接 MongoDB 失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

运行: 在 pom.xml 所在目录运行 mvn compile,然后运行 java -cp "target/classes:$(mvn dependency:build-classpath -Dmdep.outputFile=/dev/stdout)" com.example.mongodb.MongoClientExample


CRUD 操作

这是最核心的部分,我们将使用 MongoCollection 对象来操作文档。

我们定义一个简单的 Java 对象(POJO)来表示我们的文档:

User.java

package com.example.mongodb;
import org.bson.types.ObjectId;
public class User {
    private ObjectId id;
    private String name;
    private int age;
    private String city;
    // 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 String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", city='" + city + '\'' +
                '}';
    }
}

CrudOperationsExample.java

package com.example.mongodb;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.bson.types.ObjectId;
import java.util.ArrayList;
import java.util.List;
public class CrudOperationsExample {
    public static void main(String[] args) {
        String uri = "mongodb://localhost:27017";
        try (MongoClient mongoClient = MongoClients.create(uri)) {
            MongoDatabase database = mongoClient.getDatabase("mydb");
            MongoCollection<Document> collection = database.getCollection("users");
            // --- 1. 创建 ---
            System.out.println("--- 创建文档 ---");
            Document userDoc1 = new Document("name", "Alice")
                    .append("age", 30)
                    .append("city", "New York");
            collection.insertOne(userDoc1);
            System.out.println("插入文档1: " + userDoc1.getObjectId("_id"));
            Document userDoc2 = new Document("name", "Bob")
                    .append("age", 25)
                    .append("city", "London");
            collection.insertOne(userDoc2);
            System.out.println("插入文档2: " + userDoc2.getObjectId("_id"));
            // --- 2. 读取 ---
            System.out.println("\n--- 读取所有文档 ---");
            collection.find().forEach(doc -> System.out.println(doc.toJson()));
            System.out.println("\n--- 按条件读取 (name = Alice) ---");
            collection.find(new Document("name", "Alice")).forEach(doc -> System.out.println(doc.toJson()));
            // --- 3. 更新 ---
            System.out.println("\n--- 更新文档 (将 Alice 的年龄改为 31) ---");
            collection.updateOne(
                    new Document("name", "Alice"),
                    new Document("$set", new Document("age", 31))
            );
            collection.find(new Document("name", "Alice")).forEach(doc -> System.out.println("更新后: " + doc.toJson()));
            // --- 4. 删除 ---
            System.out.println("\n--- 删除文档 (age = 25) ---");
            collection.deleteOne(new Document("age", 25));
            System.out.println("删除后所有文档:");
            collection.find().forEach(doc -> System.out.println(doc.toJson()));
        }
    }
}

高级查询

MongoDB 的查询功能非常强大,使用 Filters 类可以方便地构建查询条件。

AdvancedQueriesExample.java

package com.example.mongodb;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;
import org.bson.Document;
import java.util.Arrays;
public class AdvancedQueriesExample {
    public static void main(String[] args) {
        String uri = "mongodb://localhost:27017";
        try (MongoClient mongoClient = MongoClients.create(uri)) {
            MongoDatabase database = mongoClient.getDatabase("mydb");
            MongoCollection<Document> collection = database.getCollection("users");
            // 准备一些测试数据
            collection.insertMany(Arrays.asList(
                    new Document("name", "Charlie").append("age", 35).append("city", "Paris"),
                    new Document("name", "David").append("age", 28).append("city", "Berlin"),
                    new Document("name", "Eve").append("age", 35).append("city", "Paris"),
                    new Document("name", "Frank").append("age", 40).append("city", "Tokyo")
            ));
            // 1. AND 查询: 年龄大于 30 且城市是 "Paris"
            System.out.println("--- AND 查询 (age > 30 AND city = 'Paris') ---");
            collection.find(Filters.and(
                    Filters.gt("age", 30),
                    Filters.eq("city", "Paris")
            )).forEach(doc -> System.out.println(doc.toJson()));
            // 2. OR 查询: 名字是 "David" 或者年龄小于 30
            System.out.println("\n--- OR 查询 (name = 'David' OR age < 30) ---");
            collection.find(Filters.or(
                    Filters.eq("name", "David"),
                    Filters.lt("age", 30)
            )).forEach(doc -> System.out.println(doc.toJson()));
            // 3. 排序: 按年龄升序
            System.out.println("\n--- 按年龄升序排序 ---");
            collection.find().sort(Sorts.ascending("age")).forEach(doc -> System.out.println(doc.toJson()));
            // 4. 分页: 跳过前 2 个,获取接下来的 2 个
            System.out.println("\n--- 分页 (Skip 2, Limit 2) ---");
            collection.find().skip(2).limit(2).forEach(doc -> System.out.println(doc.toJson()));
            // 清理数据
            collection.deleteMany(new Document());
        }
    }
}

索引

索引用于提高查询性能,特别是在大型集合上。

IndexExample.java

package com.example.mongodb;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class IndexExample {
    public static void main(String[] args) {
        String uri = "mongodb://localhost:27017";
        try (MongoClient mongoClient = MongoClients.create(uri)) {
            MongoDatabase database = mongoClient.getDatabase("mydb");
            MongoCollection<Document> collection = database.getCollection("users");
            // 在 "city" 字段上创建一个升序索引
            collection.createIndex(new Document("city", 1));
            System.out.println("在 'city' 字段上创建索引成功。");
            // 查看集合的所有索引
            System.out.println("\n集合 'users' 的所有索引:");
            collection.listIndexes().forEach(doc -> System.out.println(doc.toJson()));
        }
    }
}

聚合框架

聚合框架用于处理数据记录并返回计算结果,它类似于 SQL 中的 GROUP BY

AggregationExample.java

package com.example.mongodb;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Aggregates;
import org.bson.Document;
import java.util.Arrays;
public class AggregationExample {
    public static void main(String[] args) {
        String uri = "mongodb://localhost:27017";
        try (MongoClient mongoClient = MongoClients.create(uri)) {
            MongoDatabase database = mongoClient.getDatabase("mydb");
            MongoCollection<Document> collection = database.getCollection("users");
            // 准备测试数据
            collection.insertMany(Arrays.asList(
                    new Document("name", "Alice").append("department", "Sales").append("salary", 50000),
                    new Document("name", "Bob").append("department", "IT").append("salary", 60000),
                    new Document("name", "Charlie").append("department", "Sales").append("salary", 55000),
                    new Document("name", "David").append("department", "IT").append("salary", 70000)
            ));
            // 聚合操作:按部门分组,并计算每个部门的平均薪资
            System.out.println("--- 按部门分组并计算平均薪资 ---");
            collection.aggregate(Arrays.asList(
                    // 第一阶段:按 department 字段分组
                    Aggregates.group("$department",
                            // 第二阶段:计算平均值
                            Accumulators.avg("averageSalary", "$salary")
                    )
            )).forEach(doc -> System.out.println(doc.toJson()));
            // 清理数据
            collection.deleteMany(new Document());
        }
    }
}

完整项目示例

我们将所有部分整合到一个主类中,并使用 User POJO 来进行类型安全的操作,这需要使用 com.mongodb.client.model.InsertOneOptionscom.mongodb.client.result.UpdateResult 等来处理返回结果。

MainApplication.java

package com.example.mongodb;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import com.mongodb.client.model.Sorts;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.bson.Document;
import org.bson.types.ObjectId;
import java.util.ArrayList;
import java.util.List;
public class MainApplication {
    public static void main(String[] args) {
        String uri = "mongodb://localhost:27017";
        try (MongoClient mongoClient = MongoClients.create(uri)) {
            MongoDatabase database = mongoClient.getDatabase("mydb");
            MongoCollection<User> userCollection = database.getCollection("users_pojos", User.class);
            // 清理旧数据,确保每次运行都是干净的
            userCollection.deleteMany(new Document());
            System.out.println("--- 1. 创建 (Insert) ---");
            User user1 = new User();
            user1.setName("Alice");
            user1.setAge(30);
            user1.setCity("New York");
            userCollection.insertOne(user1);
            System.out.println("插入成功: " + user1.getId());
            User user2 = new User();
            user2.setName("Bob");
            user2.setAge(25);
            user2.setCity("London");
            userCollection.insertOne(user2);
            System.out.println("插入成功: " + user2.getId());
            User user3 = new User();
            user3.setName("Charlie");
            user3.setAge(30);
            user3.setCity("Paris");
            userCollection.insertOne(user3);
            System.out.println("插入成功: " + user3.getId());
            System.out.println("\n--- 2. 读取 (Find) ---");
            System.out.println("查找所有用户:");
            userCollection.find().forEach(System.out::println);
            System.out.println("\n查找年龄为 30 的用户:");
            userCollection.find(Filters.eq("age", 30)).forEach(System.out::println);
            System.out.println("\n查找年龄大于 28 的用户,只返回名字和城市:");
            userCollection.find(Filters.gt("age", 28))
                    .projection(Projections.fields(Projections.include("name", "city"), Projections.excludeId()))
                    .forEach(System.out::println);
            System.out.println("\n--- 3. 更新 (Update) ---");
            UpdateResult updateResult = userCollection.updateOne(
                    Filters.eq("name", "Alice"),
                    new Document("$set", new Document("age", 31))
            );
            System.out.println("更新了 " + updateResult.getModifiedCount() + " 个文档。");
            System.out.println("更新后的 Alice: " + userCollection.find(Filters.eq("name", "Alice")).first());
            System.out.println("\n--- 4. 删除 (Delete) ---");
            DeleteResult deleteResult = userCollection.deleteOne(Filters.eq("name", "Bob"));
            System.out.println("删除了 " + deleteResult.getDeletedCount() + " 个文档。");
            System.out.println("删除后所有用户:");
            userCollection.find().forEach(System.out::println);
            System.out.println("\n--- 5. 高级查询与聚合 ---");
            System.out.println("按年龄降序排序,并跳过第一个结果:");
            userCollection.find().sort(Sorts.descending("age")).skip(1).forEach(System.out::println);
            System.out.println("\n按年龄分组并计数:");
            // 注意:对 POJO 集合进行聚合,需要将结果映射回 Document
            userCollection.aggregate(
                    List.of(
                            new Document("$group", new Document("_id", "$age").append("count", new Document("$sum", 1)))
                    )
            ).forEach(doc -> System.out.println(doc.toJson()));
        }
    }
}

注意: 当使用泛型 MongoCollection<User.class> 时,驱动会自动进行 POJO 和 BSON 文档之间的转换,但在聚合管道中,中间结果仍然是 Document 类型,直到最后一步。


最佳实践

  1. 连接管理:

    • 使用 try-with-resources: 始终将 MongoClient 包装在 try-with-resources 语句中,以确保连接被正确关闭。
    • 不要为每个请求创建新的 MongoClient: MongoClient 是线程安全的,并且内部管理着连接池,你的整个应用应该只创建一个 MongoClient 实例,并在其生命周期内重复使用它。
  2. 异常处理:

    • 捕获 MongoException 或其子类,以处理网络问题、服务器错误等。
  3. 文档映射:

    • 对于结构化的数据,使用 POJO (如 User 类) 是一个好习惯,它提供了类型安全,使代码更易于维护。
    • 驱动支持 JSON-B、Jackson 等标准进行映射。
  4. 索引策略:

    • 为经常用于查询、排序和分组的字段创建索引。
    • 使用 explain() 方法分析查询性能,确保你的索引被正确使用。
  5. 安全性:

    • 在生产环境中,永远不要在连接字符串中硬编码用户名和密码,使用环境变量或配置文件。
    • 启用 MongoDB 的认证机制。
    • 对敏感数据进行加密。
  6. 考虑 Spring Data MongoDB:

    • 对于更复杂的项目,特别是已经使用 Spring 框架的项目,强烈推荐使用 Spring Data MongoDB
    • 它提供了更高层次的抽象,如 Repository 接口,让你可以用类似 JPA 的方式操作 MongoDB,极大地简化了数据访问层的代码。

这个指南为你提供了一个从零开始的 MongoDB Java 项目的坚实基础,你可以基于此进行扩展,构建更复杂的应用程序。

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