config.properties
#mongodb setting mongo.host=127.0.0.1 mongo.port=27017 mongo.connectionsPerHost=100 mongo.threadsAllowedToBlockForConnectionMultiplier=50 mongo.connectTimeout=1000 mongo.maxWaitTime=1500 mongo.autoConnectRetry=true mongo.socketKeepAlive=true mongo.socketTimeout=0 mongo.slaveOk=true
spring_mongo.xml
<!--引入配置属性文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- mongodb配置 --> <mongo:mongo id="mongo" replica-set="${mongo.replica-set}" write-concern="SAFE"> <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的工厂,通过它来取得mongo实例,dbname为mongodb的数据库名,没有的话会自动创建 --> <mongo:db-factory id="mongoDbFactory" dbname="uba" mongo-ref="mongo" /> <!-- 读写分离级别配置 --> <!-- 首选主节点,大多情况下读操作在主节点,如果主节点不可用,如故障转移,读操作在从节点。 --> <bean id="primaryPreferredReadPreference" class="com.mongodb.TaggableReadPreference.PrimaryPreferredReadPreference"></bean> <!-- 最邻近节点,读操作在最邻近的成员,可能是主节点或者从节点。 --> <bean id="nearestReadPreference" class="com.mongodb.TaggableReadPreference.NearestReadPreference"></bean> <!-- 从节点,读操作只在从节点, 如果从节点不可用,报错或者抛出异常。存在的问题是secondary节点的数据会比primary节点数据旧。 --> <bean id="secondaryReadPreference" class="com.mongodb.TaggableReadPreference.SecondaryReadPreference"></bean> <!-- 优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据 --> <bean id="secondaryPreferredReadPreference" class="com.mongodb.TaggableReadPreference.SecondaryPreferredReadPreference"></bean> <!-- mongodb的主要操作对象,所有对mongodb的增删改查的操作都是通过它完成 --> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> <property name="readPreference" ref="primaryPreferredReadPreference" /> </bean> <!-- 映射转换器,扫描back-package目录下的文件,根据注释,把它们作为mongodb的一个collection的映射 --> <mongo:mapping-converter base-package="dev.lzq.uba.mongo.model" /> <!-- mongodb bean的仓库目录,会自动扫描扩展了MongoRepository接口的接口进行注入 --> <mongo:repositories base-package="dev.lzq.uba.mongo.dao" />
entity
@Document(collection = "user") public class User { @Id private int id; private String name; private int age; private String city; private String mote; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getMote() { return mote; } public void setMote(String mote) { this.mote = mote; } }
dao配置
public interface MGUserDao extends MongoRepository<User, ObjectId> { /** * 方法名的严格遵守规定 * @param age * @param page * @return */ public Page<User> findByAgeGreaterThan(int age, Pageable page); /** * 有@Query声明查询, 方法名不需要严格遵守规定 * @param name * @param ageFrom * @param ageTo * @param pageable * @return */ @Query("{'name':{'$regex':?0}, 'age': {'$gte':?1,'$lte':?2}}") public Page<User> findByNameAndAgeRange(String name, int ageFrom, int ageTo, Pageable pageable); @Query("{?0:?1}") public List<User> findByAttribute(String key, String value); }
dao层的使用
MongoRepository实现了的只是最基本的增删改查的功能,要想增加额外的查询方法,可以按照以下规则定义接口的方法。自定义查询方法,格式为“findBy+字段名+方法后缀”,方法传进的参数即字段的值,此外还支持分页查询,通过传进一个Pageable对象,返回Page集合。 例如:
//查询大于age的数据 public Page<Product> findByAgeGreaterThan(int age,Pageable page) ;
下面是支持的查询类型,每三条数据分别对应:(方法后缀,方法例子,mongodb原生查询语句)
GreaterThan(大于) findByAgeGreaterThan(int age) {"age" : {"$gt" : age}} LessThan(小于) findByAgeLessThan(int age) {"age" : {"$lt" : age}} Between(在...之间) findByAgeBetween(int from, int to) {"age" : {"$gt" : from, "$lt" : to}} IsNotNull, NotNull(是否非空) findByFirstnameNotNull() {"age" : {"$ne" : null}} IsNull, Null(是否为空) findByFirstnameNull() {"age" : null} Like(模糊查询) findByFirstnameLike(String name) {"age" : age} ( age as regex) (No keyword) findByFirstname(String name) {"age" : name} Not(不包含) findByFirstnameNot(String name) {"age" : {"$ne" : name}} Near(查询地理位置相近的) findByLocationNear(Point point) {"location" : {"$near" : [x,y]}} Within(在地理位置范围内的) findByLocationWithin(Circle circle) {"location" : {"$within" : {"$center" : [ [x, y], distance]}}} Within(在地理位置范围内的) findByLocationWithin(Box box) {"location" : {"$within" : {"$box" : [ [x1, y1], x2, y2]}}}
尽管以上查询功能已经很丰富,但如果还不能满足使用情况的话可以用一下方法---基于mongodb原本查询语句的查询方式。
例一:在原接口中加入,注释Query里面的就是mongodb原来的查询语法,我们可以定义传进来的查询参数,通过坐标定义方法的参数。
@Query("{ 'name':{'$regex':?2,'$options':'i'}, sales': {'$gte':?1,'$lte':?2}}") public Page<Product> findByNameAndAgeRange(String name,double ageFrom,double ageTo,Pageable page);
例二:还可以在后面指定要返回的数据字段,如上面的例子修改如下,则只通过person表里面的name和age字段构建person对象。
@Query(value="{ 'name':{'$regex':?2,'$options':'i'}, sales':{'$gte':?1,'$lte':?2}}",fields="{ 'name' : 1, 'age' : 1}") public Page<Product> findByNameAndAgeRange(String name,double ageFrom,double ageTo,Pageable page);