MongoDB 项目集成教程


MongoDB 作为典型的 NoSQL 数据库拥有优秀的横向扩展能力,不拘束于关系型数据库中的表结构,无需调整便可实现结构变更。

今天就让我们了解下如何在普通 Maven 以及 Spring Boot 工程中集成使用 MongoDB

一、Maven集成

1. 依赖管理

在查找依赖时你可能会发现 Mongo 存在两个配置版本 mongo-java-drivermongodb-driver-sync,前者为旧版依赖其包含异步 API 相对复杂,从 MongoDB 4.0+ 开始官方建议使用 mongodb-driver-sync

简而言之,如果无兼容历史版本的需要,则优先使用 mongodb-driver-sync,依赖配置如下:

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>4.10.2</version>
</dependency>

2. 服务连接

在执行数据访问前,最基础的当然还是创建客户端连接对象,代码如下:

public void createClient() {
    String host = "localhost";
    Integer port = 27017;
    List<ServerAddress> serverList = Collections.singletonList(new ServerAddress(host, port));

    String database = "admin";
    String username = "root";
    char[] password = "123456".toCharArray();
    MongoClientSettings settings = MongoClientSettings.builder()
            // 超时配置
            .applyToSocketSettings(builder -> {
                builder.connectTimeout(60, TimeUnit.SECONDS);
                builder.readTimeout(60, TimeUnit.SECONDS);
            })
            .applyToClusterSettings(builder -> {
                builder.serverSelectionTimeout(60, TimeUnit.SECONDS).build();
                // 服务信息
                builder.hosts(serverList)
            })
            // 账号信息
            .credential(MongoCredential.createScramSha256Credential(username, database, password))
            .build();

    // 创建客户端
    MongoClient client = MongoClients.create(settings);
}

3. URI连接

MongoDB 支持多种连接格式,除了上述的连接方式外 MongoDB 同时支持以 URI 方式,其连接格式如下:

mongodb://<username>:<passsword>@<host>:<port>/<collection>

需注意一点,当用户名或密码中包含特殊字符时,在配置 uri 时需要替换为对应的转义字符,否则将无法连接。

常用的特殊字符及其转义字符参照下表:

字符 编码
@ %40
: %3A
/ %2F
? %3F
# %23
& %26
= %3D

其客户端创建类似,将上述的 credential() 替换为 applyConnectionString() 即可,实现代码如下:

String url = "mongodb://root:123456@192.168.0.21:27017/test_col?authSource=admin";
MongoClientSettings settings = MongoClientSettings.builder()
        // 超时配置
        .applyToSocketSettings(builder -> {
            builder.connectTimeout(60, TimeUnit.SECONDS);
            builder.readTimeout(60, TimeUnit.SECONDS);
        })
        .applyToClusterSettings(builder -> {
            builder.serverSelectionTimeout(60, TimeUnit.SECONDS).build();
        })
        // 服务信息
        .applyConnectionString(new ConnectionString(url))
        .build();

3. 数据新增

想要实现新增数据则十分简单,在获取 MongoCollection 实例后通过相应的 insertOne()insertMany() 方法即可。

完整调用实现代码如下:

public class MongoRepository implements AutoCloseable {

    private final String database;
    private final MongoClient mongoClient;

    public MongoRepository(String database, MongoClient mongoClient) {
        this.database = database;
        this.mongoClient = mongoClient;
    }

    @Override
    public void close() throws Exception {
        if (mongoClient != null) {
            mongoClient.close();
        }
    }

    protected MongoDatabase getDatabase() {
        return mongoClient.getDatabase(database);
    }

    public <T> void insert(String collection, T t, Class<T> tClass) {
        MongoCollection<T> mongoCollection = getDatabase().getCollection(collection, tClass);
        mongoCollection.insertOne(t);
    }

    public <T> void insertAll(String collection, List<T> list, Class<T> tClass) {
        MongoCollection<T> mongoCollection = getDatabase().getCollection(collection, tClass);
        mongoCollection.insertMany(list);
    }
}

4. 数据查询

MongoDB 查询数据与新增方式类似,这里直接通过代码演示:

public <T> void count(String collection, Map<String, ?> condition, Class<T> tClass) {
    MongoCollection<T> mongoCollection = getDatabase()
            .getCollection(collection, tClass);
    mongoCollection.countDocuments(new Document(condition));
}

public <T> T findOne(String collection, Map<String, ?> condition, Class<T> tClass) {
    MongoCollection<T> mongoCollection = getDatabase()
            .getCollection(collection, tClass);
    return mongoCollection.find(new Document(condition)).first();
}

public <T> List<T> find(String collection, Map<String, ?> condition, Class<T> tClass) {
    MongoCollection<T> mongoCollection = getDatabase()
            .getCollection(collection, tClass);
    FindIterable<T> iterable = mongoCollection.find(new Document(condition));
    List<T> list = new ArrayList<>();
    for (T t : iterable) {
        list.add(t);
    }
    return list;
}

5. 数据删除

同理,文档记录删除方式如下不再展开介绍。

public <T> boolean delete(String collection, Map<String, ?> condition, Class<T> tClass) {
    MongoCollection<T> mongoCollection = getDatabase()
            .getCollection(collection, tClass);
    return mongoCollection.deleteMany(new Document(condition)).getDeletedCount() > 0;
}

public <T> boolean deleteOne(String collection, Map<String, ?> condition, Class<T> tClass) {
    MongoCollection<T> mongoCollection = getDatabase()
            .getCollection(collection, tClass);
    return mongoCollection.deleteOne(new Document(condition)).getDeletedCount() > 0;
}

二、Spring集成

1. 依赖管理

Spring Boot 中依赖就十分简单了,引入对应的 starter 即可,依赖如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2. 连接配置

引入依赖后需在项目中配置 MongoDB 的连接信息,在 application.yml 中添加下述内容。

这里采用 URI 方式连接,与之前 Maven 方式集成中提到的类似,如果用户名或密码包含特殊字符转替换为转义字符。

spring:
  data:
    mongodb:
      uri: mongodb://root:123456@localhost:27017/test_collection?authSource=admin

3. 数据新增

完成配置后即可开始相应访问交互,与 Maven 中不同的是你可以通过 MongoTemplate 便可轻易的实现与 MongoDB 的相应交互。

MongoDB 中提供了两种新增接口 save()insert(),二者最大的区别前者新增时若数据已存在则会报错失败,而 insert() 方法则会直接覆盖旧数据。

相应的新增方法实现如下:

@Component
public class MongoRepository {

    @Autowired
    private MongoTemplate mongoTemplate;


    public <T> void save(T t) {
        mongoTemplate.save(t);
    }

    public <T> void insert(T t) {
        mongoTemplate.insert(t);
    }

    public <T> void insertAll(Collection<T> collection) {
        mongoTemplate.insertAll(collection);
    }
}

4. 数据查询

MongoDB 中通过 CriteriaQuery 构建查询条件,常用的查询接口参考下表:

方法 描述
count() 查询匹配的记录条数。
find() 返回所有匹配的记录结果。
findOne() 返回匹配记录结果中的一条。
findById() 根据文档 ID 精准匹配查询。

表中所列接口其相应的实现如下:

@Component
public class MongoRepository {

    @Autowired
    private MongoTemplate mongoTemplate;


    public <T> long count(Class<T> tClass, Map<String, Object> condition) {
        return mongoTemplate.count(createQuery(condition), tClass);
    }

    public <T> T find(Class<T> tClass, Map<String, Object> condition) {
        return mongoTemplate.findOne(createQuery(condition), tClass);
    }

    public <T> T findById(Object id, Class<T> tClass) {
        return mongoTemplate.findById(id, tClass);
    }

    public <T> List<T> findAll(Class<T> tClass, Map<String, Object> condition) {
        return mongoTemplate.find(createQuery(condition), tClass);
    }


    protected Query createQuery(Map<String, Object> conditions) {
        Criteria criteria = new Criteria();
        for (Map.Entry<String, Object> entry : conditions.entrySet()) {
            criteria.and(entry.getKey()).is(entry.getValue());
        }
        return new Query(criteria);
    }
}

文章作者: 烽火戏诸诸诸侯
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 烽火戏诸诸诸侯 !
  目录