MongoDB 与 spring 集成

本贴最后更新于 2618 天前,其中的信息可能已经水流花落

一、添加 maven 依赖

pom.xml:

<dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>2.13.0-rc0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.7.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb-cross-store</artifactId> <version>1.7.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb-log4j</artifactId> <version>1.7.1.RELEASE</version> </dependency>

二、mongodb-config.xml 的配置

在 spring-context.xml 中引入 mongodb-config.xml:

添加引入 mongoDB 配置文件:

<import resource="classpath*:/mongodb-config.xml" />

mongodb-config.xml 文件内容如下:

<?xml version="1.0" encoding="UTF-8"?> <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-4.1.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-4.1.xsd"> <!-- 加载mongodb的属性配置文件 --> <context:property-placeholder location="classpath:mongodb.properties" /> <!-- 定义mongo对象,对应的是mongodb官方jar包中的Mongo,replica-set设置集群副本的ip地址和端口 --> <mongo:mongo id="mongo" host="${mongo.host}" port="${mongo.port}"> <mongo:options connections-per-host="${mongo.connectionsPerHost}" threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}" connect-timeout="${mongo.connectTimeout}" max-wait-time="${mongo.maxWaitTime}" auto-connect-retry="${mongo.autoConnectRetry}" socket-keep-alive="${mongo.socketKeepAlive}" socket-timeout="${mongo.socketTimeout}" slave-ok="${mongo.slaveOk}" write-number="1" write-timeout="0" write-fsync="true" /> </mongo:mongo> <!-- 用户验证,在mongo.conf中配置了auth=true时使用--> <bean id="userCredentials" class="org.springframework.data.authentication.UserCredentials"> <constructor-arg name="username" value="${mongo.username}" /> <constructor-arg name="password" value="${mongo.password}" /> </bean> <!-- mongo的工厂,通过它来取得mongo实例,dbname为mongodb的数据库名,没有的话会自动创建 --> <bean id="mongoDbFactory" class="org.springframework.data.mongodb.core.SimpleMongoDbFactory"> <constructor-arg ref="mongo" /> <constructor-arg value="${mongo.dbname}" /> <!-- 用户验证,在mongo.conf中配置了auth=true时使用--> <constructor-arg ref="userCredentials" /> </bean> <bean id="mappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" /> <bean id="defaultMongoTypeMapper" class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper"> <constructor-arg name="typeKey"> <null /> </constructor-arg> </bean> <!-- collection的映射,配置MappingMongoConverter使spring-data-mongodb的java类注解生效 --> <bean id="mappingMongoConverter" class="org.springframework.data.mongodb.core.convert.MappingMongoConverter"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> <constructor-arg name="mappingContext" ref="mappingContext" /> <property name="typeMapper" ref="defaultMongoTypeMapper" /> </bean> <!-- mongodb的主要操作对象,所有对mongodb的增删改查的操作都是通过它完成 --> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> <constructor-arg name="mongoConverter" ref="mappingMongoConverter" /> </bean> </beans>

三、mongodb.properties 的配置

#数据库名称 mongo.dbname=myFirstDB #用户名 mongo.username=root #密码 mongo.password=root #主机 mongo.host=127.0.0.1 #端口号 mongo.port=27017 #一个线程变为可用的最大阻塞数 mongo.connectionsPerHost=8 #线程队列数,它以上面connectionsPerHost值相乘的结果就是线程队列最大值 mongo.threadsAllowedToBlockForConnectionMultiplier=4 #连接超时时间(毫秒) mongo.connectTimeout=1500 #最大等待时间 mongo.maxWaitTime=1500 #自动重连 mongo.autoConnectRetry=true #scoket保持活动 mongo.socketKeepAlive=true #scoket超时时间 mongo.socketTimeout=1500 #读写分离 mongo.slaveOk=true

四、实体类及其 DAO 操作类(使用 MongoTemplate)

实体类 UserAddr:

import java.io.Serializable; import java.util.List; import java.util.Map; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.GeoSpatialIndexed; import org.springframework.data.mongodb.core.mapping.Document; /** * 用户位置实体类 * @author Administrator * */ @Document(collection="userAddrs") public class UserAddr implements Serializable, Cloneable { @Id private String id; //用户id private String name; //用户名称 @GeoSpatialIndexed private Double[] loc; //地址经纬度 private String addrName; private Double distance; //相距 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double[] getLoc() { return loc; } public void setLoc(Double[] loc) { this.loc = loc; } public String getAddrName() { return addrName; } public void setAddrName(String addrName) { this.addrName = addrName; } public Double getDistance() { return distance; } public void setDistance(Double distance) { this.distance = distance; } /** * 根据map初始化对象 * @param msgMap */ public void initByMap(Map data) { String name = data.get("name").toString(); String addrName = data.get("addrName").toString(); List<Double> loc = (List<Double>)data.get("loc"); this.setName(name); this.setAddrName(addrName); this.setLoc(new Double[]{loc.get(0), loc.get(1)}); } }

实体类对应的 DAO 操作类 UserAddrsDao:

import java.util.List; import javax.annotation.Resource; import org.springframework.data.geo.GeoResult; import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.Metrics; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Repository; import com.google.common.collect.Lists; import com.ldk.mongodb.entity.UserAddr; /** * mongodb中用户位置操作DAO * @author Administrator * */ @Repository public class UserAddrsDao { @Resource private MongoTemplate mongoTemplate; /** * 插入信息 * @param userAddr */ public void insert(UserAddr userAddr) { mongoTemplate.insert(userAddr); } /** * 根据id获取信息 * @param id * @return */ public UserAddr get(String id) { return mongoTemplate.findOne( new Query(Criteria.where("id").is(id)), UserAddr.class); } /** * 根据id,更新所有信息(字段为空的将不被更新) * @param userAddr */ public void updateInfo(UserAddr userAddr) { Update update = new Update(); if(userAddr.getName() != null) update.set("name", userAddr.getName()); if(userAddr.getLoc() != null) update.set("loc", userAddr.getLoc()); if(userAddr.getAddrName() != null) update.set("addrName", userAddr.getAddrName()); mongoTemplate.upsert( new Query(Criteria.where("id").is(userAddr.getId())), update, UserAddr.class); } public void createCollection(String name) { mongoTemplate.createCollection(name); } /** * 根据id删除信息 * @param id */ public void remove(String id) { mongoTemplate.remove( new Query(Criteria.where("id").is(id)), UserAddr.class); } /** * 根据中心点坐标,查询范围内的用户地址列表。 * @param userAddr 用户地址类,其中的loc字段不能为空。 * @param maxDistance 最大距离,默认为3,单位km * @return 返回null则表示loc地址没有输入或输入错误,返回数组则表示查询到的地址列表。 * @return */ public List<UserAddr> findByLoc(UserAddr userAddr, Double maxDistance) { if(userAddr.getLoc() == null || userAddr.getLoc().length != 2) { return null; } Point point = new Point(userAddr.getLoc()[0],userAddr.getLoc()[1]); NearQuery near = NearQuery .near(point) .spherical(true) .maxDistance(maxDistance == null ? 3 : maxDistance,Metrics.KILOMETERS) //MILES以及KILOMETERS自动设置spherical(true) .distanceMultiplier(6371); List<UserAddr> resultList = Lists.newArrayList(); GeoResults<UserAddr> result = null; try { result = mongoTemplate.geoNear(near, UserAddr.class); } catch (NullPointerException e) { return resultList; } for(GeoResult<UserAddr> geoResultResult : result) { UserAddr userAddrResult = geoResultResult.getContent(); userAddrResult.setDistance(geoResultResult.getDistance().getValue()); resultList.add(userAddrResult); } return resultList; } }

五、测试

@Test public void testAdd() { // 添加一百个userAddr for (int i = 0; i < 100; i++) { UserAddr userAddr = new UserAddr(); userAddr.setId("" + i); userAddr.setName("zcy" + i); userAddr.setAddrName("坐标点" + i); userAddr.setLoc(new Double[]{121.60225, 31.21410+i*0.01}); userAddrsDao.insert(userAddr); } } @Test public void testQuery() { UserAddr userAddr = new UserAddr(); userAddr.setLoc(new Double[]{121.60225, 31.20410}); List<UserAddr> userAddrs = userAddrsDao.findByLoc(userAddr, null); System.err.println("count ====== "+userAddrs.size()); }

六、Spring 中映射 Mongodb 中注解的解释

spring-data-mongodb 中的实体映射是通过 MappingMongoConverter 这个类实现的。它可以通过注解把 java 类转换为 mongodb 的文档。

它有以下几种注解:
@Id:文档的唯一标识,在 mongodb 中为 ObjectId,它是唯一的,通过时间戳 + 机器标识 + 进程 ID+ 自增计数器(确保同一秒内产生的 Id 不会冲突)构成。

@Document:把一个 java 类声明为 mongodb 的文档,可以通过 collection 参数指定这个类对应的文档。

@Document(collection="users"):标识实体类在 mongodb 中对应的集合。

@DBRef:声明类似于关系数据库的关联关系。ps:暂不支持级联的保存功能,当你在本实例中修改了 DERef 对象里面的值时,单独保存本实例并不能保存 DERef 引用的对象,它要另外保存,如下面例子的 Person 和 Account。

@Indexed:声明该字段需要索引,建索引可以大大的提高查询效率。

@CompoundIndex:复合索引的声明,建复合索引可以有效地提高多字段的查询效率。

@GeoSpatialIndexed :声明该字段为地理信息的索引。

@Field:代表一个字段,可以不加,不加的话默认以参数名为列名。

@Transient:映射忽略的字段,该字段不会保存到 mongodb。

@PersistenceConstructor:声明构造函数,作用是把从数据库取出的数据实例化为对象。该构造函数传入的值为从 DBObject 中取出的数据

参考:https://www.cnblogs.com/byteworld/p/5963112.html

  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖 • 6 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...