Spring与MongoDB集成使用

Spring与MongoDB结合

  • 前言
  • POM依赖
  • applicationContext文件
  • 使用代码

前言

公司让将一些离线数据,如交易订单、记账信息等数据存入MongoDB这样的,最像关系型的非关系型数据库中,于是我便开始研究怎样通过Spring方便地使用MongoDB,这里记录一下使用和配置的过程。
MongoDB这种可以在集合中任意增加字段的存储方式,非常适合公司多变的业务,并且其可配置为分布式的存储方式,非常适合横向扩展。MongoDB集合中的每条记录可设置索引,并且也支持聚合等运算,因此,在业务计算不是特别复杂,没有多表关联查询的场景,并且存储数据量非常庞大的场景下,可以考虑使用MongoDB作为数据存储的方式。

本文的配置及代码编写参考了Spring的官方文档 [ Spring Data MongoDB ]

POM依赖

这里说明一下,以下的配置JDK版本必须要升级至8,Spring版本需要是4。
往pom.xml文件中添加如下两个依赖。

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>2.0.0.M1</version>
</dependency>
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.3.0</version>
</dependency>

为什么依赖这两个版本呢,因为公司的仓库里只有这个版本,如果往里加的话还要申请,太麻烦了。
就先这么用着。

编写applicationContext.xml文件

这里我是通过applicationContext.xml文件来配置Spring的MongoDbTemplate的。具体的配置内容如下:

    <bean id="mongoCredential" class="com.mongodb.MongoCredential" 
            factory-method="createCredential">
        <constructor-arg value="${cashbase_balance_mongodb_username}"/>
        <constructor-arg value="admin"/>
        <constructor-arg value="${cashbase_balance_mongodb_password}"/>
    </bean>
    <bean id="userCredential" 
        class="org.springframework.data.authentication.UserCredentials">
        <constructor-arg>
            <null/>
        </constructor-arg>
        <constructor-arg>
            <null/>
        </constructor-arg>
    </bean>

    <bean id="mongoClientOptions" class="com.***.MongoClientUtils"
          factory-method="getMongoClientOptions"/>

    <bean id="mongoClient" class="com.mongodb.MongoClient">
        <constructor-arg 
            value="${cashbase_balance_mongodb_host}:${cashbase_balance_mongodb_port}"/>
        <constructor-arg>
            <list>
                <ref bean="mongoCredential"/>
            </list>
        </constructor-arg>
        <constructor-arg ref="mongoClientOptions"/>

    </bean>

    <bean id="mongoFactory" class="org.springframework.data.mongodb.core.SimpleMongoDbFactory">
        <constructor-arg ref="mongoClient"/>
        <constructor-arg value="${mongo_database}"/>
        <constructor-arg ref="userCredential"/>
    </bean>

    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg ref="mongoFactory"/>
    </bean>

从以上的配置中,可以看出,我的配置还是相当麻烦的。为什么会配得这么麻烦,因为按照官方文档给出的配置方法,可以使用mongo标签进行配置,但是我添加了相应的xmlns和xsi后,还是会提示我找不到标签之类等错误。并且标签的配置方法会造成初始化MongoDBFactory等初始化的错误,从错误信息来看是mongodb的版本和spring版本之间不兼容导致的。因此,干脆用最原始的方法来生成bean。

  • mongoTemplate

    mongoTemplate是我们用于增删改查等操作的对象,在之后的代码示例中会再解释。初始化它需要使用mongoDbFactory。

  • mongoDbFactory

    mongoDbFactory是一个提供数据库连接的工厂对象,这个接口目前只有一个实现类。它需要一个mongoClient对象,待连接的数据库名称(String对象)以及一个用户认证对象userCredential。这里比较特殊的一点是这个userCredential的用户名和密码必须为空字符串,而真正的安全性信息,需要填写在mongoCredential对象中

  • mongoClient

    这个对象需传入你的mongoDB连接地址,以及端口号,然后再传入mongoCredential这个bean,从配置文件中,可以看出,这个bean的构造方法必须传两个null,代表账号和密码。在Factory的源码中,如果你的mongoCredential对象中,账号和密码包含有非null的值,是会抛异常的。在我用的spring-data-mongodb版本中,账密的设置已经迁移到mongoCredential中了。这个对象还需提供一个ClientOption,这里可以设置你的定制化配置。我写的这个Option如下,只设置了一个超时时间:

import com.mongodb.MongoClientOptions;

public class MongoClientUtils {
    public static MongoClientOptions getMongoClientOptions() {
        MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
        builder.socketTimeout(10 * 1000);
        return builder.build();
    }
}


  • mongoCredential

mongoCredential对象可以设置客户端与MongoDB的安全通信方式,这里我使用的是默认的通信方式。此对象的构造方法需要传递连接到MongoDB的账户和密码,以及提供首选的库名,我这里写的是admin。

使用代码

上一节就是整个初始化的过程,下面说一下MongoTemplate的用法。

在我们的业务代码中,主要使用mongoTemplate进行常见的增删改查操作,代码如下。


import static org.springframework.data.mongodb.core.query.Criteria.where;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * mongoDb,从mongo中读写数据
 * Created by on 17-9-14
 */
@Component
public class MerchantMongoDAO {

    @Autowired
    private MongoTemplate mongoTemplate;

    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * Insert if not Exists otherwise update
     *
     * @param merchantReportInfo merchantReportInfo
     */
    public void save(MerchantReportInfo merchantReportInfo) {
        if (Objects.isNull(merchantReportInfo)) {
            logger.info("insert object MerchantReportInfo is null");
            return;
        }
        merchantReportInfo.setId(merchantReportInfo.getReportIndex());
        String collectionName = "t_bal_merchant_monthly_summary";
        if (!mongoTemplate.collectionExists(collectionName)) {
            mongoTemplate.createCollection(collectionName);
        }
        logger.info("存入mongoDb,merchantReportInfo={}", merchantReportInfo);
        mongoTemplate.save(merchantReportInfo, collectionName);
    }

    /**
     * 通过mode和accountNo查询
     *
     * @param mode            模式
     * @param accountingMonth 商户帐号
     * @return List<MerchantReportInfo>
     */
    public List<MerchantReportInfo> query(int mode, int accountingMonth) {
        String collectionName = "t_bal_merchant_monthly_summary";
        Query query = new Query(where("month").is(accountingMonth).and("reportMode").is(mode));
        query.with(new Sort(new Sort.Order(Sort.Direction.ASC, "merchantId")));
        return mongoTemplate.find(query, MerchantReportInfo.class, collectionName);
    }
}

以上两段代码提供了插入和查询这两个操作。这个插入操作呢,就是无记录插入,有记录则更新。默认情况下mongoTemplate会以对象中的id字段作为主键。查询有Query、Where、Sort等方法,和SQL非常相近,比较好用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值