众所周知,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之内。