Spring整合MongoDB
2015-08-10 17:08
721 查看
1、Maven导入依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>ren.benben</groupId> <artifactId>diary</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>diary Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 设置变量:用于统一管理Library的版本 --> <javax.version>7.0</javax.version> <javax.servlet.version>3.1.0</javax.servlet.version> <javax.servlet.jstl.version>1.2</javax.servlet.jstl.version> <log4j.version>1.2.16</log4j.version> <org.slf4j.version>1.7.1</org.slf4j.version> <junit.version>4.12</junit.version> <org.htmlparser.version>2.1</org.htmlparser.version> <org.springframework.version>4.1.1.RELEASE</org.springframework.version> <spring-data-mongodb.version>1.7.1.RELEASE</spring-data-mongodb.version> <org.mongodb.version>3.0.3</org.mongodb.version> <javax.validation.version>1.1.0.Final</javax.validation.version> <org.hibernate.version>5.0.2.Final</org.hibernate.version> </properties> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>${javax.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${javax.servlet.jstl.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${javax.servlet.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>${org.slf4j.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.htmlparser</groupId> <artifactId>htmlparser</artifactId> <version>${org.htmlparser.version}</version> </dependency> <!-- spring framework --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${org.springframework.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>${spring-data-mongodb.version}</version> </dependency> <!-- javax.validation相关 --> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>${javax.validation.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>${org.hibernate.version}</version> </dependency> </dependencies> <build> <finalName>diary</finalName> </build> </project>
我们这里使用的Spring基础框架是4.1.x版本,使用1.7.x版本的Spring Data MongoDB对MongoDB进行CRUD操作。在使用Spring Data MongoDB框架时,需要使用到JSR-303 Validation验证标准。于是我们在这里引入 javax.validation的Jar和Hibernate Validator。值得注意的是,这里使用到的Hibernate Validator,不是我们要引入Hibernate框架,而仅仅是引入JSR-303的实现。
2、Spring对MongoDB的配置
2.1 我的配置
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task" xmlns:mongo="http://www.springframework.org/schema/data/mongo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.7.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd"> <context:component-scan base-package="ren.benben.diary" /> <mongo:mongo host="127.0.0.1" port="27017" /> <!-- mongo的工厂,通过它来取得mongo实例,dbname为mongodb的数据库名,没有的话会自动创建 --> <mongo:db-factory dbname="diary" mongo-ref="mongo" /> <!-- mongodb的主要操作对象,所有对mongodb的增删改查的操作都是通过它完成 --> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> </bean> <context:annotation-config /> </beans>
上面是我使用的配置。
2.2 mongo:mongo
这里通过mongo:mongo标签来配置数据库的地址和端口,此标签默认的bean名称为mongo。如果你还需要配置MongoDB的其它参数,可以使用mongo:options标签。<mongo:mongo host="localhost" port="27017"> <mongo:options connections-per-host="8" threads-allowed-to-block-for-connection-multiplier="4" connect-timeout="1000" max-wait-time="1500}" auto-connect-retry="true" socket-keep-alive="true" socket-timeout="1500" slave-ok="true" write-number="1" write-timeout="0" write-fsync="true"/> </mongo:mongo/>
当然,在设置MongoDB参数时,也可以使用Java属性文件。
<context:property-placeholder location="classpath:/com/myapp/mongodb/config/mongo.properties"/> <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>
2.3 mongo:db-factory
当你设置完MongoDB的基本参数后,你还得设置一个mongo数据工厂。此过程是由mongo:db-factory完成的,此标签的主要作用是通过它来取得mongo实例,dbname为diary的数据库名,没有的话会自动创建。这里mongo-ref引用的就是上文mongo:mongo这个bean。mongo:db-factory标签默认的bean名称为mongoDbFactory。
<mongo:db-factory dbname="diary" mongo-ref="mongo" />
如果你的DB需要用户名和密码才能访问的话,也可以通过mongo:db-factory来设置。
<mongo:db-factory id="anotherMongoDbFactory" host="localhost" port="27017" dbname="database" username="benben" password="123456"/>
2.4 MongoTemplate
设置完mongo:db-factory后,我们就可以设置MongoTemplate了。MongoTemplate是Spring对MongoDB进行CRUD操作的主要工具类,其作用类似Spring整合Hibernate时的HibernateTemplate。<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> </bean>
到这里为止,我们获取到MongoTemplate,配置就告一段落。
3、实体类与映射
新建一个文章Article实体类,对应数据库的article集合。package ren.benben.diary.article.model; import java.sql.Timestamp; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; /** * 文章 * @ClassName: Article * @Description: TODO * @author 笨笨 * @date 2015年7月29日 下午2:19:58 * */ @Document(collection = "article") public class Article { @Id private String id; private String title; private String descript; private String link; private String[] tags; private Timestamp createTime; private Timestamp updateTime; private Integer state; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescript() { return descript; } public void setDescript(String descript) { this.descript = descript; } public String getLink() { return link; } public void setLink(String link) { this.link = link; } public String[] getTags() { return tags; } public void setTags(String[] tags) { this.tags = tags; } public Timestamp getCreateTime() { return createTime; } public void setCreateTime(Timestamp createTime) { this.createTime = createTime; } public Integer getState() { return state; } public void setState(Integer state) { this.state = state; } public Timestamp getUpdateTime() { return updateTime; } public void setUpdateTime(Timestamp updateTime) { this.updateTime = updateTime; } }
3.1 @Document
使用@Document注解将实体类与数据库的集合相互映射。collection的值是数据库的集合名称。加上@Document注解后,Spring的自动扫描功能就能识别出你的映射的实体类了。
3.2 _id属性
MongoDB需要我们为所有的文档都加上’_id’属性,其实就相当于SQL中的主键。所以我们在创建实体类时,也需要为实体类加一个id映射。Spring Data MongoDB提供了多种方式,在实体类中映射_id
直接在实体类中定义一个名为id的字符串属性
private String id;
为实体类中的任意属性加上@Id注解
@Id private String id;
@Id private String x;
如果没特殊的需要,我们最好是使用@Id注解为标注名为id的属性作为_id,像我们demo中的实体类一样。这样程序的可读性高点。
3.3 @Field
实体类的非_id属性,不加任何注解。可以同名的映射到数据库的集合中。如果你非得跟数据库中的不一样,Spring也提供了@Field为实现。如,我们想把上文中的link属性,保存到集合的url属性中。
@Field("url") private String link;
4、DAO基类及使用
4.1 IBaseDao接口及其实现
package ren.benben.diary.api; import java.util.List; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; /** * IBaseDao接口 * @ClassName: IBaseDao * @Description: TODO * @author 笨笨 * @date 2015年8月10日 下午3:15:40 * * @param <T> */ public interface IBaseDao<T> { /** * 获取查询数据的数量 * @Title: findCount * @Description: TODO * @param @param query * @param @return * @return Long * @throws */ public Long findCount(Query query); /** * 查询数据 * @Title: find * @Description: TODO * @param @param query * @param @return * @return List<T> * @throws */ public List<T> find(Query query); /** * 分页查询数据 * @Title: findList * @Description: TODO * @param @param start * @param @param limit * @param @return * @return List<T> * @throws */ public List<T> findList(int start, int limit); /** * 根据id获取单个数据 * @Title: findOne * @Description: TODO * @param @param id * @param @return * @return T * @throws */ public T findOne(String id); /** * 插入一条数据 * @Title: insert * @Description: TODO * @param @param entity * @return void * @throws */ public void insert(T entity); /** * 更新数据 * @Title: update * @Description: TODO * @param @param entity * @param @throws Exception * @return void * @throws */ public void update(T entity) throws Exception; /** * 更新数据 * @Title: update * @Description: TODO * @param @param query * @param @param update * @return void * @throws */ public void update(Query query,Update update); /** * 删除数据 * @Title: remove * @Description: TODO * @param @param entity * @return void * @throws */ public void remove(T entity); }
package ren.benben.diary.api; import java.lang.reflect.ParameterizedType; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Order; 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 ren.benben.diary.api.util.MongoFactory; /** * IBaseDao接口实现 * @ClassName: BaseDao * @Description: TODO * @author 笨笨 * @date 2015年8月10日 下午3:57:18 * * @param <T> */ public class BaseDao<T> implements IBaseDao<T> { private Class<T> clazz; public BaseDao() { ParameterizedType type = (ParameterizedType) getClass() .getGenericSuperclass(); clazz = (Class<T>) type.getActualTypeArguments()[0]; } @Autowired private MongoTemplate mongoTemplate; @Autowired private MongoFactory mongoFactory; public List<T> find(Query query){ return mongoTemplate.find(query, clazz); } public List<T> findList(int skip, int limit) { Query query = new Query(); query.with(new Sort(new Order(Direction.ASC, "_id"))); query.skip(skip).limit(limit); return find(query); } public T findOne(String id) { Query query = new Query(); query.addCriteria(new Criteria("_id").is(id)); return mongoTemplate.findOne(query, clazz); } public void insert(T entity) { mongoTemplate.insert(entity); } public void update(T entity) throws Exception { Map<String, Object> map = mongoFactory.converObjectToParams(entity); Query query = new Query(); query.addCriteria(new Criteria("_id").is(map.get("id"))); Update update = (Update) map.get("update"); this.update(query, update); } public void update(Query query,Update update){ mongoTemplate.updateFirst(query, update, clazz); } public Long findCount(Query query){ return mongoTemplate.count(query, clazz); } public void remove(T entity){ mongoTemplate.remove(entity); } public MongoTemplate getMongoTemplate() { return mongoTemplate; } }
在DAO基类实现上,我们自己写了一个MongoFactory的工具类。此类主要是在做更新的时候使用。在update(T entity)方法中,做到类似HibernateTemplate一样,通过MongoFactory获取到entity的id及entity值不为空的属性,以id作为条件,更新这些属性。
相关的两个辅助工具类如下:
package ren.benben.diary.api.util; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Component; /** * Mongo辅助类 * @ClassName: MongoFactory * @Description: TODO * @author 笨笨 * @date 2015年8月10日 下午4:02:07 * */ @Component public class MongoFactory { @Autowired private ObjectParams objectParams; /** * 把实体对象转为MongoDB更新需要的值 * @Title: converObjectToParams * @Description: TODO * @param @param obj * @param @return * @param @throws Exception * @return Map<String,Object> * @throws */ public Map<String, Object> converObjectToParams(Object obj) throws Exception{ Map<String, Object> map = new HashMap<String, Object>(); Update update = new Update(); Map<String, String> params = objectParams.createParams(obj); String id = params.get("id"); Set<Map.Entry<String, String>> set = params.entrySet(); for (Iterator<Map.Entry<String, String>> it = set.iterator(); it.hasNext();) { Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next(); if(!entry.getKey().equals("id")){ update.set(entry.getKey(), entry.getValue()); } } map.put("id", id); map.put("update", update); return map; } }
package ren.benben.diary.api.util; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Component; /** * 实体参数映射工具 * @ClassName: ObjectParams * @Description: TODO * @author 笨笨 * @date 2015年8月10日 下午4:05:35 * */ @Component public class ObjectParams { private String javaType = "java"; /** * 获取查询的参数 * * @param object * @return * @throws Exception */ public Map<String, String> createParams(Object object) throws Exception { Map<String, String> params = new HashMap<String, String>(); setIntoParams(params,object, null); return params; } private void setIntoParams(Map<String, String> params,Object object, String fatherName) throws IllegalAccessException, Exception { Field[] fields = object.getClass().getDeclaredFields(); for (Field file : fields) { boolean accessFlag = file.isAccessible(); file.setAccessible(true); String name = file.getName(); Object value = file.get(object); if(file.getType().getName().equals("java.lang.Class")){ break; }else if(file.getType().getName().contains(javaType)){ if(fatherName != null && !fatherName.equals(" ")){ name = fatherName+"."+name; } if(value != null){ params.put(name, value+""); } }else{ if(value != null){ setIntoParams(params,file.get(object), name); } } file.setAccessible(accessFlag); } } }
4.2 使用BaseDao
建立Article实体类的Dao。package ren.benben.diary.article.dao; import java.util.List; import ren.benben.diary.api.IBaseDao; import ren.benben.diary.api.util.Pagination; import ren.benben.diary.article.model.Article; /** * Article的Dao接口 * @ClassName: IArticleDao * @Description: TODO * @author 笨笨 * @date 2015年8月10日 下午4:09:25 * */ public interface IArticleDao extends IBaseDao<Article>{ /** * 根据link属性获取一条数据 * @Title: findOneByLink * @Description: TODO * @param @param link * @param @return * @return Article * @throws */ public Article findOneByLink(String link); /** * 根据link属性与title属性进行或运算获取一条数据 * @Title: findOneByLinkOrTitle * @Description: TODO * @param @param link * @param @param title * @param @return * @return Article * @throws */ public Article findOneByLinkOrTitle(String link,String title); /** * 根据state属性获取createTime为最新的数据 * @Title: findNewestByState * @Description: TODO * @param @param state * @param @return * @return Article * @throws */ public Article findNewestByState(Integer state); /** * 根据state属性获取数据的数量 * @Title: findNewestByState * @Description: TODO * @param @param state * @param @return * @return Article * @throws */ public Long findCount(Integer state); /** * 分页获取数据 * @Title: findListByPage * @Description: TODO * @param @param page * @param @param state * @param @return * @return List<Article> * @throws */ public List<Article> findListByPage(Pagination page,Integer state); }
package ren.benben.diary.article.dao.impl; import java.util.List; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; 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 org.springframework.stereotype.Repository; import ren.benben.diary.api.BaseDao; import ren.benben.diary.api.constant.Constant; import ren.benben.diary.api.util.Pagination; import ren.benben.diary.article.dao.IArticleDao; import ren.benben.diary.article.model.Article; /** * Article的Dao实现 * @ClassName: ArticleDao * @Description: TODO * @author 笨笨 * @date 2015年8月10日 下午4:14:21 * */ @Repository public class ArticleDao extends BaseDao<Article> implements IArticleDao { public Article findOneByLink(String link) { Query query = new Query(Criteria.where("link").is(link)); return getMongoTemplate().findOne(query, Article.class); } public Article findNewestByState(Integer state){ Query query = createQuery(state); query.limit(1).with(new Sort(new Sort.Order(Sort.Direction.DESC,"createTime"))); List<Article> list = this.find(query); if(list.size()>0){ return list.get(0); } return null; } public List<Article> findListByPage(Pagination page,Integer state) { Query query = createQuery(state); query.with(page.getSort()); query.skip(page.getSkip()).limit(page.getPageSize());// 从skip开始,取多少条记录 return this.find(query); } public Long findCount(Integer state){ Query query = createQuery(state); return this.findCount(query); } private Query createQuery(Integer state){ Query query = new Query(); query.addCriteria(Criteria.where("state").is(state)); return query; } public Article findOneByLinkOrTitle(String link, String title) { Query query = new Query( new Criteria().orOperator(Criteria.where("title").is(title), Criteria.where("link").is(link)) ); return getMongoTemplate().findOne(query, Article.class); } }
分页辅助类:
package ren.benben.diary.api.util; import java.util.List; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import ren.benben.diary.api.constant.Constant; /** * 分页辅助类 * @ClassName: Pagination * @Description: TODO * @author 潘广伟 * @date 2015年8月10日 下午4:15:51 * */ public class Pagination { /** 每页数量 */ private Integer pageSize; /** 开始位置 */ private Integer skip; /** 当前页 */ private Integer currentPage; /** 总页数 */ private Long totalPage; /** 查询到的总数据量 */ private Long totalNumber; /** 数据集 */ private List items; /** 排序 */ private Sort sort; public Pagination(int currentPage, Long totalNumber) { this.pageSize = Constant.PAGE_SIZE; this.currentPage = currentPage; this.totalNumber = totalNumber; this.totalPage = totalNumber / pageSize + 1; this.skip = (currentPage - 1) * pageSize; this.sort = new Sort(new Sort.Order(Direction.ASC, "_id")); } public Integer getCurrentPage() { return currentPage; } public void setCurrentPage(Integer currentPage) { this.currentPage = currentPage; } public Long getTotalPage() { return totalPage; } public void setTotalPage(Long totalPage) { this.totalPage = totalPage; } public Long getTotalNumber() { return totalNumber; } public void setTotalNumber(Long totalNumber) { this.totalNumber = totalNumber; } public List getItems() { return items; } public void setItems(List items) { this.items = items; } public Integer getPageSize() { return pageSize; } public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } public Integer getSkip() { return skip; } public void setSkip(Integer skip) { this.skip = skip; } public Sort getSort() { return sort; } public void setSort(String dir, boolean isAsc) { if (isAsc) { this.sort = new Sort(new Sort.Order(Direction.ASC, dir)); } else { this.sort = new Sort(new Sort.Order(Direction.DESC, dir)); } } }
5、测试及小优化
5.1 测试数据插入及_class属性的移除
单元测试代码:package diary; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import ren.benben.diary.api.util.DateFactory; import ren.benben.diary.article.dao.IArticleDao; import ren.benben.diary.article.model.Article; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/applicationContext.xml") public class MongoTest { @Autowired private IArticleDao articleDao; @Autowired private DateFactory factory; @Test public void testInsert(){ try { Article article = new Article(); article.setTitle("标题1"); article.setLink("http://benben.ren"); article.setState(1); article.setCreateTime(factory.now()); articleDao.insert(article); } catch (Exception e) { e.printStackTrace(); } } }
测试结果:
我们看到测试结果中,除了我们想要保存的属性值外,还多了一个_class的属性。这是由Spring默认帮我们加到集合中的。它可能并不是我们需要的,且这个数据还占着存储空间。如果我们想把这个属性去掉,可以通过配置MappingMongoConverter的typeMapper来实现。
<bean id="mappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" /> <!-- 默认Mongodb类型映射 --> <bean id="defaultMongoTypeMapper" class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper"> <constructor-arg name="typeKey"> <null /><!-- 这里设置为空,可以把 spring data mongodb 多余保存的_class字段去掉 --> </constructor-arg> </bean> <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>
5.2 测试简单查询及类型转换器
单元测试代码:@Test public void testFindOne() { try { Article article = articleDao.findOne("55c85750a192cfe9d93e1cf1"); System.out.println(article.getTitle()); System.out.println(article.getCreateTime()); } catch (Exception e) { e.printStackTrace(); } }
测试结果:
信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type java.util.Date to type java.sql.Timestamp at org.springframework.core.convert.support.GenericConversionService.handleConv erterNotFound(GenericConversionService.java:311) at org.springframework.core.convert.support.GenericConversionService.convert(Ge nericConversionService.java:192) at org.springframework.core.convert.support.GenericConversionService.convert(Ge nericConversionService.java:173) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPoten tiallyConvertedSimpleRead(MappingMongoConverter.java:821) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValu e(MappingMongoConverter.java:1187) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.access$2 00(MappingMongoConverter.java:78) at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbP ropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1133) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getValue Internal(MappingMongoConverter.java:869) at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWith PersistentProperty(MappingMongoConverter.java:282) at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWith PersistentProperty(MappingMongoConverter.java:270) at org.springframework.data.mapping.model.BasicPersistentEntity.doWithPropertie s(BasicPersistentEntity.java:309) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(Map pingMongoConverter.java:270) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(Map pingMongoConverter.java:231) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(Map pingMongoConverter.java:191) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(Map pingMongoConverter.java:187) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(Map pingMongoConverter.java:78) at org.springframework.data.mongodb.core.MongoTemplate$ReadDbObjectCallback.doW ith(MongoTemplate.java:2200) at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(M ongoTemplate.java:1837) at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate. java:1654) at org.springframework.data.mongodb.core.MongoTemplate.findOne(MongoTemplate.ja va:563) at org.springframework.data.mongodb.core.MongoTemplate.findOne(MongoTemplate.ja va:558) at ren.benben.diary.api.BaseDao.findOne(BaseDao.java:56) at diary.MongoTest.testFindOne(MongoTest.java:41) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57 ) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl .java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod. java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.j ava:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.ja va:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.jav a:17) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallba cks.evaluate(RunBeforeTestMethodCallbacks.java:72) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbac ks.evaluate(RunAfterTestMethodCallbacks.java:81) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(Spr ingRepeat.java:72) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(Spr ingJUnit4ClassRunner.java:216) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(Spr ingJUnit4ClassRunner.java:82) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbac ks.evaluate(RunBeforeTestClassCallbacks.java:60) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallback s.evaluate(RunAfterTestClassCallbacks.java:67) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJU nit4ClassRunner.java:162) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestRef erence.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:3 8) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRu nner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRu nner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner. java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner .java:192)
这里报无法将java.util.Date转换成java.sql.Timestamp。原因是我们实体类中的时间是Timestamp类型的,而Spring Data默认的时间类型是Date。
这里我们需要一个转换器。
package ren.benben.diary.api.converter; import java.sql.Timestamp; import java.util.Date; import org.springframework.core.convert.converter.Converter; /** * Timestamp转换器 * 将Date转换成Timestamp * @ClassName: TimestampConverter * @Description: TODO * @author 笨笨 * @date 2015年8月10日 下午4:45:19 * */ public class TimestampConverter implements Converter<Date, Timestamp>{ public Timestamp convert(Date date) { if(date != null){ return new Timestamp(date.getTime()); } return null; } }
配置TimestampConverter转换器到Spring中。由于我们在上面做移除_class属性优化的时候,使用到了MappingMongoConverter,而MongoTemplate只有一个mongoConverter属性,所以我们需要将DefaultMongoTypeMapper引入新的Converter中。
<!-- 默认Mongodb类型映射 --> <bean id="defaultMongoTypeMapper" class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper"> <constructor-arg name="typeKey"> <null /><!-- 这里设置为空,可以把 spring data mongodb 多余保存的_class字段去掉 --> </constructor-arg> </bean> <!-- 转换器:1、去掉write的_class字段 2、TimestampConverter --> <mongo:mapping-converter id="mongoConverter" base-package="ren.benben.diary.api.converter" type-mapper-ref="defaultMongoTypeMapper"> <mongo:custom-converters> <mongo:converter> <bean class="ren.benben.diary.api.converter.TimestampConverter" /> </mongo:converter> </mongo:custom-converters> </mongo:mapping-converter> <!-- mongodb的主要操作对象,所有对mongodb的增删改查的操作都是通过它完成 --> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> <constructor-arg name="mongoConverter" ref="mongoConverter" /> </bean>
再次测试得到结果:
5.3 使用分页查询
使用代码(Service层使用)public Pagination findArticles(Integer currentPage, Integer state) { Long count = articleDao.findCount(state); Pagination page = new Pagination(currentPage, count); page.setSort("creatTime", false); page.setItems(articleDao.findListByPage(page, state)); return page; }
这里是获取文章总数,获取currentPage页count条数据。并按creatTime降序排序。
具体就不详细展开了。
5.4 注意
BaseDao中做更新数据的时候,我们使用到了java映射机制来获取实体对象的值,并更新这些值。如果更新的属性值不是太多的话,建议不要使用BaseDao的update(T entity)方法,因为通过映射获取值没有直接获取来得快。6、链接
Mongodb的简单使用:http://blog.csdn.net/jrainbow/article/details/39163843
Spring MVC的简单用法:
http://blog.csdn.net/jrainbow/article/details/46618077
HibernateTemplate与HibernateDaoSupport:
http://blog.csdn.net/jrainbow/article/details/10526617
相关文章推荐
- 分享微信开发Html5轻游戏中的几个坑
- PHP添加yaf xhprof mongodb 同理
- mongodb安装
- maven学习
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- maven插件maven-war-plugin的使用
- 如何在 Ubuntu 上安装 MongoDB
- perl操作MongoDB报错undefined symbol: HeUTF8解决方法
- C#中使用1.7版本驱动操作MongoDB简单例子
- MongoDB系列教程(四):设置用户访问权限
- php实现的mongodb操作类实例
- 解决mongodb在ubuntu下启动失败,提示couldn‘t remove fs lock errno:9 Bad file descriptor的错误
- 在PostgreSQL的基础上创建一个MongoDB的副本的教程
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- java操作mongodb示例分享
- struts2 spring整合fieldError问题
- php对mongodb的扩展(初出茅庐)