(文章的编写虽然不至于花费很多时间,但转载请注明来源。本文参考了:http://liuluo129.iteye.com/blog/1994045,在此基础上进行了部分优化,及详细的介绍了流程)
1.首先引入Maven 依赖,如果不是用Maven管理项目,那么应该下载对应的Jar包并添加到项目lib下
1 <dependency> 2 <groupId>org.springframework.data</groupId> 3 <artifactId>spring-data-mongodb</artifactId> 4 <version>1.4.1.RELEASE</version> 5 </dependency> 6 7 <dependency> 8 <groupId>org.mongodb</groupId> 9 <artifactId>casbah_2.9.3</artifactId> 10 <version>2.7.0-RC2</version> 11 </dependency>
2.Spring中配置MongoDB,创建 spring-mongo.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-3.2.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.2.xsd"> <!--mongoDB--> <context:property-placeholder location="classpath:config.properties" /> <!-- Default bean name is 'mongo' --> <mongo: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:db-factory id="mongoDbFactory" dbname="kycloud" mongo-ref="mongo" /> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> </bean> <!-- 映射转换器,扫描back-package目录下的文件,根据注释,把它们作为mongodb的一个collection的映射 --> <!-- <mongo:mapping-converter base-package="net.xxx.mongo.**" />--> <!-- mongodb bean的仓库目录,会自动扫描扩展了MongoRepository接口的接口进行注入 --> <!--<mongo:repositories base-package="net.xxx.mongo.**"/>--> <context:annotation-config /> </beans>
3. config.properties 内容
#-------------- MongoDB mongo.host=localhost mongo.port=27017 mongo.connectionsPerHost=8 mongo.threadsAllowedToBlockForConnectionMultiplier=3 mongo.connectTimeout=3000 mongo.maxWaitTime=1500 mongo.autoConnectRetry=true mongo.socketKeepAlive=true mongo.socketTimeout=2000 mongo.slaveOk=true
4.将spring-mongo.xml引入到web.xml 目的当然是使Spring容器能检测并加载到容器中
<servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:/applicationContext-mvc.xml,classpath*:/applicationContext-data-jpa.xml,classpath*:/spring-mongo.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
5.关键的部分 注解及查询套件的构建
QueryField.java
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * type表示查询类似,默认为equals * attribute表示要查询的属性,默认为空串,如果为空则为字段名称 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface QueryField { QueryType type() default QueryType.EQUALS; String attribute() default ""; }
QueryType.java
import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.util.StringUtils; import java.lang.reflect.Field; import java.util.List; /** * 查询媒介 * 1. equals:相等 * 2. like:mongodb的like查询 * 3. in:用于列表的in类型查询 */ public enum QueryType { EQUALS { @Override public Criteria buildCriteria(QueryField queryFieldAnnotation, Field field, Object value) { if (check(queryFieldAnnotation, field, value)) { String queryField = getQueryFieldName(queryFieldAnnotation, field); return Criteria.where(queryField).is(value.toString()); } return new Criteria(); } }, LIKE { @Override public Criteria buildCriteria(QueryField queryFieldAnnotation, Field field, Object value) { if (check(queryFieldAnnotation, field, value)) { String queryField = getQueryFieldName(queryFieldAnnotation, field); return Criteria.where(queryField).regex(value.toString()); } return new Criteria(); } }, IN { @Override public Criteria buildCriteria(QueryField queryFieldAnnotation, Field field, Object value) { if (check(queryFieldAnnotation, field, value)) { if (value instanceof List) { String queryField = getQueryFieldName(queryFieldAnnotation, field); // 此处必须转型为List,否则会在in外面多一层[] return Criteria.where(queryField).in((List<?>)value); } } return new Criteria(); } }; private static boolean check(QueryField queryField, Field field, Object value) { return !(queryField == null || field == null || value == null); } public abstract Criteria buildCriteria(QueryField queryFieldAnnotation, Field field, Object value); /** * 如果实体bean的字段上QueryField注解没有设置attribute属性时,默认为该字段的名称 * * @param field * @return */ private static String getQueryFieldName(QueryField queryField, Field field) { String queryFieldValue = queryField.attribute(); if (!StringUtils.hasText(queryFieldValue)) { queryFieldValue = field.getName(); } return queryFieldValue; } }
QueryField.java和QueryType.ava的编写的目的是为了公用Dao服务。注意不要引入错误的包。
6.公用Dao的构建
MongoDao.java
package net.shopxx.commons.component.mongo; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import java.util.List; public interface MongoDao<T> { //保存一个对象到mongodb public T save(T bean); // 根据id删除对象 public void deleteById(T t); // 根据对象的属性删除 public void deleteByCondition(T t); // 通过条件查询更新数据 public void update(Query query, Update update); // 根据id进行更新 public void updateById(String id, T t); // 通过条件查询实体(集合) public List<T> find(Query query); public List<T> findByCondition(T t); // 通过一定的条件查询一个实体 public T findOne(Query query); // 通过ID获取记录 public T get(String id); // 通过ID获取记录,并且指定了集合名(表的意思) public T get(String id, String collectionName); public MongoTemplate getMongoTemplate(); }
实现类MongoDaoSupport.java
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.util.List; public abstract class MongoDaoSupport<T> implements MongoDao<T> { @Autowired @Qualifier("mongoTemplate") protected MongoTemplate mongoTemplate; //保存一个对象到mongodb public T save(T bean) { mongoTemplate.save(bean); return bean; } // 根据id删除对象 public void deleteById(T t) { mongoTemplate.remove(t); } // 根据对象的属性删除 public void deleteByCondition(T t) { Query query = buildBaseQuery(t); mongoTemplate.remove(query, getEntityClass()); } // 通过条件查询更新数据 public void update(Query query, Update update) { mongoTemplate.updateMulti(query, update, this.getEntityClass()); } // 根据id进行更新 public void updateById(String id, T t) { Query query = new Query(); query.addCriteria(Criteria.where("id").is(id)); Update update = buildBaseUpdate(t); update(query, update); } // 通过条件查询实体(集合) public List<T> find(Query query) { return mongoTemplate.find(query, this.getEntityClass()); } public List<T> findByCondition(T t) { Query query = buildBaseQuery(t); return mongoTemplate.find(query, getEntityClass()); } // 通过一定的条件查询一个实体 public T findOne(Query query) { return mongoTemplate.findOne(query, this.getEntityClass()); } // 通过ID获取记录 public T get(String id) { return mongoTemplate.findById(id, this.getEntityClass()); } // 通过ID获取记录,并且指定了集合名(表的意思) public T get(String id, String collectionName) { return mongoTemplate.findById(id, this.getEntityClass(), collectionName); } // 根据vo构建查询条件Query private Query buildBaseQuery(T t) { Query query = new Query(); Field[] fields = t.getClass().getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); try { Object value = field.get(t); if (value != null) { QueryField queryField = field.getAnnotation(QueryField.class); if (queryField != null) { query.addCriteria(queryField.type().buildCriteria(queryField, field, value)); } } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return query; } private Update buildBaseUpdate(T t) { Update update = new Update(); Field[] fields = t.getClass().getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); try { Object value = field.get(t); if (value != null) { update.set(field.getName(), value); } } catch (Exception e) { e.printStackTrace(); } } return update; } // 获取需要操作的实体类class @SuppressWarnings("unchecked") protected Class<T> getEntityClass() { return ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]); } public MongoTemplate getMongoTemplate() { return mongoTemplate; } }
7.-------------------------------正式开始使用
>>>实体
import net.xxx.commons.component.mongo.QueryField; public class DeviceToken extends BaseEntity { @QueryField private Long uid; @QueryField private String token; @QueryField private String device; @QueryField private String userAgent; public DeviceToken(Long uid, String token, String device, String userAgent) { this.uid = uid; this.token = token; this.device = device; this.userAgent = userAgent; } public Long getUid() { return uid; } public void setUid(Long uid) { this.uid = uid; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public String getDevice() { return device; } public void setDevice(String device) { this.device = device; } public String getUserAgent() { return userAgent; } public void setUserAgent(String userAgent) { this.userAgent = userAgent; } }
>>>Service
public interface DeviceTokenService extends MongoDao<DeviceToken> { }
>>>ServiceImpl
@Service("deviceTokenServiceImpl") public class DeviceTokenServiceImpl extends MongoDaoSupport<DeviceToken> implements DeviceTokenService { }
>>> 应用
@Resource private DeviceTokenService deviceTokenService; //注入到需要应用的文件 //查询示例 List<DeviceToken> dts= deviceTokenService.find(new BasicQuery(new BasicDBObject("uid",uid),new BasicDBObject("userAgent",userAgent)));
具体其他方法的使用可以扩充MongDao 和MongoDaoSupport.