众所周知,spring集成的一些nosql或者sql数据库,都习惯用xxxxTemplate。一般看到xxxxTemplate,我们就可以认为是spring集成的。要和原生的使用方式区分开来。这里,我们不讨论在java项目中原生的mongodb的使用方式,单讨论spring提供的mongodb的封装。

在此之前,我们有必要了解下mongodb的数据存储格式。我一般用json格式存储,结构如下代码所示。如何查看mongodb的数据,可以使用mongoVUE工具。我们可以在Mongodb中存储数亿级别的这种数据而不影响效率。提醒一下:Mongodb不适合按照多条件查询,我们一般用id值来做查询。多条件查询时需要建索引,而且容易把库查死。

{
  "_id" : "123456789",
  "_class" : "com.OrderInfo",
  "historyId" : "123456789_1_2",
  "orderId" : NumberLong("123456789"),
  "orderDirection" : "正向",
  "overStatus" : "已完成",
  "orgArea" : "华北",
  "org" : "总公司",
  "orderType" : "一般订单",
  "paymentType" : "货到付款",
  "paymentTpyeGroup" : "后款",
  "orderPrice" : 0.0,
  "duePrice" : 0.0,
  "payPrice" : 1000.0,
  "tuiKuanPrice" : 0.0,
  "diffPrice" : -1000.0,
  "memberId" : "testlzg",
  "laiyuan" : "站点",
  "invoicePutType" : "未开票",
  "operationTime" : "20190104160726",
  "status" : "完成",
  "carrier" : "测试操作单位",
  "ttsj" : "20190104160726",
  "waybillSign" : "300000000000000",
  "operateNodeSystem" : "站点-妥投",
  "bizNodeType" : "站点",
  "bizNodeName" : "测试操作单位",
  "bizNodeCode" : "910",
  "belongSystem" : "TMS",
  "systemCode" : "josl",
  "operater" : "张三",
  "operaterErp" : "1122",
  "distributeType" : "65",
  "endDate" : "20190104160726",
  "validTag" : "1",
  "orderStatus" : "暂停",
  "duizhangStatus" : "足额对账",
  "updateTime" : ISODate("2016-10-10T03:16:52.068Z"),
  "orgId" : "6",
  "createTime" : "20161010111636",
  "damagedPrice" : 0.0,
  "tmplateNode" : "妥投"
}

要想在spring程序中使用mongodb,我们应该怎么做呢。

首先:

引入mongodb的jar包

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

当然,如果不使用maven,你有可以单独直接下载spring-data-mongodb-1.3.3.jar引入到你的项目中。

其次:

需要在我们的spring的配置文件中增加Mongodb的配置。

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mongo="http://www.springframework.org/schema/data/mongo"
	xsi:schemaLocation="http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          http://www.springframework.org/schema/data/mongo
          http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <mongo:mongo id="mongo_Test" replica-set="ip1:port1,ip2:port2"><!--配置mongodb服务器和端口,这里是基于复制级的,可以配置一主多从-->

    <mongo:options connections-per-host="100"
                       threads-allowed-to-block-for-connection-multiplier="4"
                       connect-timeout="2000"
                       max-wait-time="3000"
                       auto-connect-retry="true"
                       socket-keep-alive="true"
                       socket-timeout="10000"
                       slave-ok="true"
                       write-number="1"
                       write-timeout="0"
                       write-fsync="false"/> <!--控制数据写的时候,是否刷新完磁盘返回-->
    </mongo:mongo>

    <mongo:db-factory id="mongoDbFactoryPrism" dbname="dbname" username="username" password="${password}" mongo-ref="mongo_Test"/>

    <bean id="mongoTemplateTest" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="<span style="font-family: Arial, Helvetica, sans-serif;">mongoDbFactoryPrism</span><span style="font-family: Arial, Helvetica, sans-serif;">" /></span>
	  <property name="writeResultChecking" value="EXCEPTION" /><!--控制mongodb是否抛异常-->
	  <property name="writeConcern" value="SAFE" /><!--控制mongodb的安全级别-->
    </bean>
    <bean id="mongoDBCache" class="com..MongoDBCacheImpl">
        <property name="mongoOperations" ref="mongoTemplateTest"/>
    </bean>
</beans>

这种配置是不是一目了然呢。spring中好多封装配置也就这样,一环扣一环,最后给我们一个可以用的手把,例如 mongoDBCache。



最后:

我们就可以通过实现我们的MongoDBCacheImpl来写我们的业务逻辑了。

public class MongoDBCacheImpl {

    public void setMongoOperations(MongoOperations mongoOperations) {
        this.mongoOperations = mongoOperations;
    }

    private MongoOperations mongoOperations;
//根据key获取
    public <T> T getByKey(Object key, Class<T> entityClass) {
        return mongoOperations.findById(key, entityClass);
    }

    public <T> List<T> getByColumn(String columnName, Object columeValue, Class<T> entityClass) {
        return mongoOperations.find(new Query(Criteria.where(columnName).is(columeValue)), entityClass);
    }
//保存
    public void save(Object obj) {
        mongoOperations.save(obj);
    }
//移除
    public void remove(Object obj) {
        mongoOperations.remove(obj);
    }

    public <T> Long getCountByDate(Date beginTime, Date endTime, Class<T> entityClass) {

        Assert.notNull(beginTime, "beginTime is not null.");
        Assert.notNull(endTime, "endTime is not null.");
        Assert.isTrue(endTime.after(beginTime), "endTime must be after beginTime.");

        return mongoOperations.count(new Query(Criteria.where("createdate").gte(beginTime).and("createdate").lt(endTime)), entityClass);

    }

    public <T> List<T> findAllByDate(Date beginTime, Date endTime, Class<T> entityClass) {
        Assert.notNull(beginTime, "beginTime is not null.");
        Assert.notNull(endTime, "endTime is not null.");
        Assert.isTrue(endTime.after(beginTime), "endTime must be after beginTime.");

        Query query = new Query().addCriteria(
                Criteria.where("riqi").exists(true)
                        .andOperator(Criteria.where("riqi").gte(beginTime),Criteria.where("riqi").lt(endTime)));
        return mongoOperations.find(query, entityClass);

    }

    public <T> List<T> findAllByDateAndColumn(String dateColumnName, Date beginTime, Date endTime, String columnName, Object columeValue, Class<T> entityClass) {

        Query query = new Query().addCriteria(
                Criteria.where(dateColumnName).exists(true)
                        .andOperator(Criteria.where(dateColumnName).gte(beginTime),Criteria.where(dateColumnName).lt(endTime))
                        .and(columnName).is(columeValue));
        return mongoOperations.find(query, entityClass);
    }
    
//统计
    public <T> Long  getCountByDateAndColumn(String dateColumnName, Date beginTime, Date endTime, String columnName, Object columeValue, Class<T> entityClass) {

        Query query = new Query().addCriteria(
                Criteria.where(dateColumnName).exists(true)
                        .andOperator(Criteria.where(dateColumnName).gte(beginTime),Criteria.where(dateColumnName).lt(endTime))
                        .and(columnName).is(columeValue));

        return mongoOperations.count(query,entityClass);
    }
//分页查询
    public <T> Pagination<T> getPageListByDateColumn(String dateColumnName, Date beginTime, Date endTime, Pagination<T> page, Class<T> entityClass) {
        Query query = new Query().addCriteria(
                Criteria.where(dateColumnName).exists(true)
                        .andOperator(Criteria.where(dateColumnName).gte(beginTime),Criteria.where(dateColumnName).lte(endTime)));
        if (null != page && page.getTotalCount()>0){

                page.setTotalCount(page.getTotalCount());
                query.skip(page.getFirstResult());
                query.limit(page.getPageSize());

        }else {

            return null;
        }

        List<T> pageData = mongoOperations.find(query,entityClass);
        page.setDatas(pageData);

        return page;
    }
//按照Key更新
    public <T> void updateByKey(Object key, String updateColumn, Object value, Class<T> entityClass) {
        Query query = new Query(Criteria.where( "_id" ).is(key));
        mongoOperations.updateFirst(query,Update.update(updateColumn,value),entityClass);
    }
//删除指定key
    public <T> void deleteByKey(Object key, Class<T> entityClass) {
        Query query = new Query(Criteria.where( "_id" ).is(key));
        mongoOperations.remove(query,entityClass);
    }
//删除所有
    public <T> void removeAll(String dateColumnName, Date beginTime, Date endTime, String columnName, Object columeValue, Class<T> entityClass){
        Query query = new Query().addCriteria(
                Criteria.where(dateColumnName).exists(true)
                        .andOperator(Criteria.where(dateColumnName).gte(beginTime),Criteria.where(dateColumnName).lte(endTime))
                        .and(columnName).is(columeValue));
        mongoOperations.remove(query,entityClass);
    }

}


至此,我们就可以用mongodb对我们的数据进行增删改查了,对于复制级的mongodb,数据量在3亿以上,更新查询操作也一般在5ms之内。