Spring Data 与MongoDB 集成一:入门篇(开发环境搭建和简单CRUD)
来源:互联网 发布:php中级开发工程师 编辑:程序博客网 时间:2024/05/22 10:29
一、简介
SpringData 项目提供与MongoDB文档数据库的集成。
二、SpringData 与MongoDB 配置及对应Jar包
1、安装mongodb 数据库,请查考:待补充
2、下载spring-data 关联两个子项目:spring-data-commons和spring-data-mongodb
我下载的jar 文件是:
spring-data-commons-1.7.2.RELEASE.jar
spring-data-mongodb-1.4.2.RELEASE.jar
3、下载mongodb的驱动包.
我下载的jar 文件是:
mongo-java-driver-3.0.4.jar
4、测试mongodb 数据库是否能够连接:两种方式(java代码方式和mongodb 工具方式(Robomongo 0.9.0-RC10))
java代码连接方式:
package com.spring.main;import java.util.Set;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.mongodb.DB;import com.mongodb.Mongo;@RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试 @ContextConfiguration(locations={"classpath*:mongodb.xml"}) public class MongodbConnection {@Testpublic void connection(){try{ // 连接到 mongodb 服务 Mongo mongo = new Mongo("192.168.1.88", 27017); //根据mongodb数据库的名称获取mongodb对象 , DB db = mongo.getDB( "database" ); Set<String> collectionNames = db.getCollectionNames(); // 打印出test中的集合 for (String name : collectionNames) { System.out.println("collectionName==="+name); } }catch(Exception e){ e.printStackTrace(); } }}
测试结果:
mongodb.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.1.xsdhttp://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"><!-- Default bean name is 'mongo' --><mongo:mongo host="192.168.1.88" port="27017" /><mongo:db-factory dbname="database" mongo-ref="mongo" /><bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"><constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /></bean><bean id="businessDao" class="com.spring.operation.BusinessDao"></bean><bean id="businessPositionDao" class="com.spring.operation.BusinessPositionDao"></bean><bean id="mongoDaoImpl" class="com.spring.operation.MongoDaoImpl"></bean></beans>
Robomongo 0.9.0-RC10连接特定mongodb 数据库
三、SpringData 实现Mongodb CRUD简单封装:
1、实现一个基础接口,是比较通用的BaseMongoDao.java类
package com.spring.mongodb;import java.util.List;import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import com.mongodb.WriteResult; public interface BaseMongoDao<T> { /** * 插入 */ public T save(T entity); /** * 根据ID查询 */ public T findById(String id); /** * 通过ID获取记录,并且指定了集合名(表的意思) */ public T findById(String id, String collectionName); /** * 获得所有该类型记录 */ public List<T> findAll(); /** * 获得所有该类型记录,并且指定了集合名(表的意思) */ public List<T> findAll(String collectionName); /** * 根据条件查询 */ public List<T> find(Query query); /** * 根据条件查询一个 */ public T findOne(Query query); /** * 分页查询 */ public Page<T> findPage(Page<T> page, Query query); /** * 根据条件 获得总数 */ public long count(Query query); /** * 根据条件 更新 */ public WriteResult update(Query query, Update update); /** * 更新符合条件并sort之后的第一个文档 并返回更新后的文档 */ public T updateOne(Query query, Update update); /** * 根据传入实体ID更新 */ public WriteResult update(T entity); /** * 根据条件 删除 * * @param query */ public void remove(Query query); }
2、编写基础通用类BaseMongoDaoImpl ,继承BaseMongoDao
package com.spring.mongodb;import java.lang.reflect.Field; import java.util.List; import javax.annotation.Resource; 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 com.mongodb.WriteResult; public class BaseMongoDaoImpl<T> implements BaseMongoDao<T> {/** * spring mongodb 集成操作类 */ @Resource protected MongoTemplate mongoTemplate; /** * 注入mongodbTemplate * * @param mongoTemplate */ protected void setMongoTemplate(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } public T save(T entity) { mongoTemplate.insert(entity); return entity; } public T findById(String id) { return mongoTemplate.findById(id, this.getEntityClass()); } public T findById(String id, String collectionName) { return mongoTemplate.findById(id, this.getEntityClass(), collectionName); } public List<T> findAll() { return mongoTemplate.findAll(this.getEntityClass()); } public List<T> findAll(String collectionName) { return mongoTemplate.findAll(this.getEntityClass(), collectionName); } public List<T> find(Query query) { return mongoTemplate.find(query, this.getEntityClass()); } public T findOne(Query query) { return mongoTemplate.findOne(query, this.getEntityClass()); } public Page<T> findPage(Page<T> page, Query query) { //如果没有条件 则所有全部 query=query==null?new Query(Criteria.where("_id").exists(true)):query; long count = this.count(query); // 总数 page.setTotalCount((int) count); int currentPage = page.getCurrentPage(); int pageSize = page.getPageSize(); query.skip((currentPage - 1) * pageSize).limit(pageSize); List<T> rows = this.find(query); page.build(rows); return page; } public long count(Query query) { return mongoTemplate.count(query, this.getEntityClass()); } public WriteResult update(Query query, Update update) { if (update==null) { return null; } return mongoTemplate.updateMulti(query, update, this.getEntityClass()); } public T updateOne(Query query, Update update) { if (update==null) { return null; } return mongoTemplate.findAndModify(query, update, this.getEntityClass()); } public WriteResult update(T entity) { Field[] fields = this.getEntityClass().getDeclaredFields(); if (fields == null || fields.length <= 0) { return null; } Field idField = null; // 查找ID的field for (Field field : fields) { if (field.getName() != null && "id".equals(field.getName().toLowerCase())) { idField = field; break; } } if (idField == null) { return null; } idField.setAccessible(true); String id=null; try { id = (String) idField.get(entity); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } if (id == null || "".equals(id.trim())) return null; // 根据ID更新 Query query = new Query(Criteria.where("_id").is(id)); // 更新 // Update update = new Update(); // for (Field field : fields) { // // 不为空 不是主键 不是序列化号 // if (field != null // && field != idField // && !"serialversionuid" // .equals(field.getName().toLowerCase())) { // field.setAccessible(true); // Object obj = field.get(entity); // if (obj == null) // continue; // update.set(field.getName(), obj); // } // } Update update = ReflectionUtils.getUpdateObj(entity); if (update == null) { return null; } return mongoTemplate.updateFirst(query, update, getEntityClass()); } public void remove(Query query) { mongoTemplate.remove(query, this.getEntityClass()); } /** * 获得泛型类 */ private Class<T> getEntityClass() { return ReflectionUtils.getSuperClassGenricType(getClass()); } }
package com.spring.entity;import java.io.Serializable;public class Business implements Serializable {/** * */private static final long serialVersionUID = 1L;//维度private double lat;//经度private double lng;//商家编号private int openid;//默认构造函数public Business() {super();}//set和get public double getLat() {return lat;}public void setLat(double lat) {this.lat = lat;}public double getLng() {return lng;}public void setLng(double lng) {this.lng = lng;}public int getOpenid() {return openid;}public void setOpenid(int openid) {this.openid = openid;}}
4、编写BuinessDao 类文件,继承BaseMongoDaoImpl<T>,实现对Buiness的CRUD操作。
package com.spring.operation;import com.spring.entity.Business;import com.spring.mongodb.BaseMongoDaoImpl;public class BusinessDao extends BaseMongoDaoImpl<Business> {}
5、实例测试
package com.spring.main;import java.util.List;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;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.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.spring.entity.Business;import com.spring.mongodb.Page;import com.spring.operation.BusinessDao;@RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试 @ContextConfiguration(locations={"classpath*:mongodb.xml"}) public class MongodbMain {@Autowired private BusinessDao businessDao; //测试数据插入 @Test public void test1(){ Business business =new Business(); business.setLat(22.588402); business.setLng(113.867822); business.setOpenid(5); businessDao.save(business); System.out.println("数据插入成功"); } //测试数据获取(id)@Testpublic void test2(){Business business = businessDao.findById("582174af6e6407195c0cd10a");System.out.println("商家编号:"+business.getOpenid());System.out.println("经度:"+business.getLat());System.out.println("维度:"+business.getLng());}//测试数据获取(id,collectionName)@Testpublic void test3(){Business business = businessDao.findById("582175986e64071f888bee69","business");System.out.println("商家编号:"+business.getOpenid());System.out.println("经度:"+business.getLat());System.out.println("维度:"+business.getLng());}//测试数据获取(all)@Testpublic void test4(){List<Business> list = businessDao.findAll();if(list !=null && list.size()>0){for(Business business : list){System.out.println("商家编号:"+business.getOpenid());System.out.println("经度:"+business.getLat());System.out.println("维度:"+business.getLng());}}}//测试数据获取(collectionName)@Testpublic void test5(){List<Business> list = businessDao.findAll("business");if(list !=null && list.size()>0){for(Business business : list){System.out.println("商家编号:"+business.getOpenid());System.out.println("经度:"+business.getLat());System.out.println("维度:"+business.getLng());}}}//测试数据获取(query); 注意请求参数属性与实体对象属性一一对应。@Testpublic void test6(){Query query = new Query(Criteria.where("lng").is(114.038804).and("lat").is(22.669214).and("openid").is(2));List<Business> list = businessDao.find(query);if(list !=null && list.size()>0){for(Business business : list){System.out.println("商家编号:"+business.getOpenid());System.out.println("经度:"+business.getLat());System.out.println("维度:"+business.getLng());}}}//测试数据获取(query); 注意请求参数属性与实体对象属性一一对应。@Testpublic void test7(){Query query = new Query(Criteria.where("lng").is(114.038804).and("lat").is(22.669214).and("openid").is(2));Business business = businessDao.findOne(query);if(business !=null){System.out.println("商家编号:"+business.getOpenid());System.out.println("经度:"+business.getLat());System.out.println("维度:"+business.getLng());}}//测试数据获取(page);@Testpublic void test8(){Query query = new Query();Page<Business> page = new Page<Business>();//page.setPageSize(2); //设置分页记录数//page.setCurrentPage(3);//设置当前页面Page<Business> pages = businessDao.findPage(page, query);List<Business> list = pages.getRows();if(list !=null && list.size()>0){for(Business business :list){System.out.println("商家编号:"+business.getOpenid());System.out.println("经度:"+business.getLat());System.out.println("维度:"+business.getLng());}}}//测试数据获取(total)@Testpublic void test9(){Query query = new Query();long num = businessDao.count(query);System.out.println("记录总数:"+num);}//测试数据修改(update) 注意:修改返回的实体对象是之前存储的数据信息@Testpublic void test10(){Query query = new Query(Criteria.where("openid").is(2));Update update =new Update();update.set("lng", 110.649865);Business business = businessDao.updateOne(query, update);if(business !=null){System.out.println("商家编号:"+business.getOpenid());System.out.println("经度:"+business.getLat());System.out.println("维度:"+business.getLng());}}}
6、相关工具类封装(Page.java[java分页工具类])和(ReflectionUtils(反射工具类))
package com.spring.mongodb;import java.io.Serializable; import java.util.List; public class Page<T> implements Serializable { private static final long serialVersionUID = 5760097915453738435L; public static final int DEFAULT_PAGE_SIZE = 10; /** * 每页显示个数 */ private int pageSize; /** * 当前页数 */ private int currentPage; /** * 总页数 */ private int totalPage; /** * 总记录数 */ private int totalCount; /** * 结果列表 */ private List<T> rows; public Page(){ this.currentPage = 1; this.pageSize = DEFAULT_PAGE_SIZE; } public Page(int currentPage,int pageSize){ this.currentPage=currentPage<=0?1:currentPage; this.pageSize=pageSize<=0?1:pageSize; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getTotalPage() { return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } /** * 设置结果 及总页数 * @param list */ public void build(List<T> rows) { this.setRows(rows); int count = this.getTotalCount(); int divisor = count / this.getPageSize(); int remainder = count % this.getPageSize(); this.setTotalPage(remainder == 0 ? divisor == 0 ? 1 : divisor : divisor + 1); } public List<T> getRows() { return rows; } public void setRows(List<T> rows) { this.rows = rows; } }
package com.spring.mongodb;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.util.HashMap;import java.util.Map;import org.slf4j.Logger;import org.slf4j.LoggerFactory;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.util.Assert;import org.springframework.util.StringUtils;public class ReflectionUtils {private static Logger logger = LoggerFactory.getLogger(ReflectionUtils.class);/** * 调用Getter方法. */public static Object invokeGetterMethod(Object obj, String propertyName) {String getterMethodName = "get" + StringUtils.capitalize(propertyName);return invokeMethod(obj, getterMethodName, new Class[] {},new Object[] {});}/** * 调用Setter方法.使用value的Class来查找Setter方法. */public static void invokeSetterMethod(Object obj, String propertyName,Object value) {invokeSetterMethod(obj, propertyName, value, null);}/** * 调用Setter方法. * * @param propertyType * 用于查找Setter方法,为空时使用value的Class替代. */public static void invokeSetterMethod(Object obj, String propertyName,Object value, Class<?> propertyType) {Class<?> type = propertyType != null ? propertyType : value.getClass();String setterMethodName = "set" + StringUtils.capitalize(propertyName);invokeMethod(obj, setterMethodName, new Class[] { type },new Object[] { value });}/** * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. */public static Object getFieldValue(final Object obj, final String fieldName) {Field field = getAccessibleField(obj, fieldName);if (field == null) {throw new IllegalArgumentException("Could not find field ["+ fieldName + "] on target [" + obj + "]");}Object result = null;try {result = field.get(obj);} catch (IllegalAccessException e) {logger.error("不可能抛出的异常{}", e.getMessage());}return result;}/** * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. */public static void setFieldValue(final Object obj, final String fieldName,final Object value) {Field field = getAccessibleField(obj, fieldName);if (field == null) {throw new IllegalArgumentException("Could not find field ["+ fieldName + "] on target [" + obj + "]");}try {field.set(obj, value);} catch (IllegalAccessException e) {logger.error("不可能抛出的异常:{}", e.getMessage());}}/** * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. * * 如向上转型到Object仍无法找到, 返回null. */public static Field getAccessibleField(final Object obj,final String fieldName) {Assert.notNull(obj, "object不能为空");Assert.hasText(fieldName, "fieldName");for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {try {Field field = superClass.getDeclaredField(fieldName);field.setAccessible(true);return field;} catch (NoSuchFieldException e) {// NOSONAR// Field不在当前类定义,继续向上转型}}return null;}/** * 直接调用对象方法, 无视private/protected修饰符. 用于一次性调用的情况. */public static Object invokeMethod(final Object obj,final String methodName, final Class<?>[] parameterTypes,final Object[] args) {Method method = getAccessibleMethod(obj, methodName, parameterTypes);if (method == null) {throw new IllegalArgumentException("Could not find method ["+ methodName + "] on target [" + obj + "]");}try {return method.invoke(obj, args);} catch (Exception e) {throw convertReflectionExceptionToUnchecked(e);}}/** * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 如向上转型到Object仍无法找到, 返回null. * * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... * args) */public static Method getAccessibleMethod(final Object obj,final String methodName, final Class<?>... parameterTypes) {Assert.notNull(obj, "object不能为空");for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {try {Method method = superClass.getDeclaredMethod(methodName,parameterTypes);method.setAccessible(true);return method;} catch (NoSuchMethodException e) {// NOSONAR// Method不在当前类定义,继续向上转型}}return null;}/** * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class. eg. public UserDao * extends HibernateDao<User> * * @param clazz * The class to introspect * @return the first generic declaration, or Object.class if cannot be * determined */@SuppressWarnings({ "unchecked", "rawtypes" })public static <T> Class<T> getSuperClassGenricType(final Class clazz) {return getSuperClassGenricType(clazz, 0);}/** * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class. * * 如public UserDao extends HibernateDao<User,Long> * * @param clazz * clazz The class to introspect * @param index * the Index of the generic ddeclaration,start from 0. * @return the index generic declaration, or Object.class if cannot be * determined */@SuppressWarnings("rawtypes")public static Class getSuperClassGenricType(final Class clazz,final int index) {Type genType = clazz.getGenericSuperclass();if (!(genType instanceof ParameterizedType)) {logger.warn(clazz.getSimpleName()+ "'s superclass not ParameterizedType");return Object.class;}Type[] params = ((ParameterizedType) genType).getActualTypeArguments();if (index >= params.length || index < 0) {logger.warn("Index: " + index + ", Size of "+ clazz.getSimpleName() + "'s Parameterized Type: "+ params.length);return Object.class;}if (!(params[index] instanceof Class)) {logger.warn(clazz.getSimpleName()+ " not set the actual class on superclass generic parameter");return Object.class;}return (Class) params[index];}/** * 将反射时的checked exception转换为unchecked exception. */public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {if (e instanceof IllegalAccessException|| e instanceof IllegalArgumentException|| e instanceof NoSuchMethodException) {return new IllegalArgumentException("Reflection Exception.", e);} else if (e instanceof InvocationTargetException) {return new RuntimeException("Reflection Exception.",((InvocationTargetException) e).getTargetException());} else if (e instanceof RuntimeException) {return (RuntimeException) e;}return new RuntimeException("Unexpected Checked Exception.", e);}/** * 根据对象获得mongodb Update语句 除id字段以外,所有被赋值的字段都会成为修改项 */public static Update getUpdateObj(final Object obj) {if (obj == null)return null;Field[] fields = obj.getClass().getDeclaredFields();Update update = null;boolean isFirst = true;for (Field field : fields) {field.setAccessible(true);try {Object value = field.get(obj);if (value != null) {if ("id".equals(field.getName().toLowerCase())|| "serialversionuid".equals(field.getName().toLowerCase()))continue;if (isFirst) {update = Update.update(field.getName(), value);isFirst = false;} else {update = update.set(field.getName(), value);}}} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}return update;}/** * 根据对象获得mongodb Query语句 * * 1.时间范围查询:在时间字段前增加begin或end,为这两个字段分别赋值 例:private Date createDate; 开始时间 * private Date beginCreateDate; 结束时间 private Date endCreateDate; * 分析后结果:where createDate >= beginCreateDate and createDate < * beginCreateDate * * 2.排序 定义并赋值VO中 orderBy 字段,以英文“,”分割多个排序,以空格分隔排序方向 asc可不写 例:private String * orderBy; orderBy="createDate desc,sendDate asc,id" 分析结构:order by * createDate desc,sendDate asc,id asc * * 3.固定值搜索 定义并赋值VO中的任意字段,搜索时会把以赋值的字段当作为搜索条件 */public static Query getQueryObj(final Object obj) {if (obj == null)return null;Field[] fields = obj.getClass().getDeclaredFields();// Sort sort=new Sort(new Order(Direction.DESC,"createDate"));Query query = new Query();// 存放日期范围或者确定日期Map<String, Criteria> dateMap = new HashMap<String, Criteria>();String sortStr = null;for (Field field : fields) {field.setAccessible(true);try {Object value = field.get(obj);if (value != null) {if ("serialversionuid".equals(field.getName().toLowerCase())) {continue;}if ("orderby".equals(field.getName().toLowerCase())) {sortStr = String.valueOf(value);continue;}if (field.getType().getSimpleName().equals("Date")) {if (field.getName().toLowerCase().startsWith("begin")) {String beginName = field.getName().substring(5);if (beginName.isEmpty()) {dateMap.put("begin", Criteria.where("begin").is(value));} else {//beginName = StringUtil//.toLowerCaseFirstOne(beginName);Criteria criteria = dateMap.get(beginName) == null ? Criteria.where(beginName).gte(value) : dateMap.get(beginName).gte(value);dateMap.put(beginName, criteria);}continue;}if (field.getName().toLowerCase().startsWith("end")) {String endName = field.getName().substring(3);if (endName.isEmpty()) {dateMap.put("end",Criteria.where("end").is(value));} else {//endName = StringUtil//.toLowerCaseFirstOne(endName);Criteria criteria = dateMap.get(endName) == null ? Criteria.where(endName).lt(value) : dateMap.get(endName).lt(value);dateMap.put(endName, criteria);}continue;}dateMap.put(field.getName(),Criteria.where(field.getName()).is(value));continue;}query.addCriteria(Criteria.where(field.getName()).is(value));}} catch (Exception e) {e.printStackTrace();}}// 日期类型查询条件for (String key : dateMap.keySet()) {if (dateMap.get(key) != null) {query.addCriteria(dateMap.get(key));}}// 排序if (sortStr != null && !sortStr.trim().isEmpty()) {Sort sort = null;String[] strs = sortStr.split(",");for (String str : strs) {str = str.trim();if (str.isEmpty()) {continue;}int i = str.indexOf(" ");if (i < 0) {if (sort == null) {sort = new Sort(Direction.ASC, str);} else {sort = sort.and(new Sort(Direction.ASC, str));}} else {String name = str.substring(0, i);String dire = str.substring(i + 1).trim();Sort sn = null;if ("desc".equals(dire.toLowerCase())) {sn = new Sort(Direction.DESC, name);} else {sn = new Sort(Direction.ASC, name);}if (sort == null) {sort = sn;} else {sort = sort.and(sn);}}}if (sort != null) {query.with(sort);}}return query;}}
项目源码:待补充。
0 1
- Spring Data 与MongoDB 集成一:入门篇(开发环境搭建和简单CRUD)
- Spring Data 与MongoDB 集成一:入门篇(开发环境搭建和简单CRUD)
- Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)
- Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)
- Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)
- Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)
- Spring-data + MongoDb简单环境搭建
- spring MongoDB 集成crud操作(简单封装)
- spring MongoDB 集成crud操作(简单封装)
- 简单的spring-data集成mongoDB项目,实现crud的功能
- mongodb学习(搭建开发环境+简单入门)
- Spring Data 与MongoDB 集成三:操作篇(修改)
- Spring Data 与MongoDB 集成四:操作篇(查询)
- Spring Data 与MongoDB 集成五:操作篇(分页)
- Spring Data MongoDB 环境搭建
- Spring Data 与MongoDB 集成二:操作篇(添加和删除)
- Spring Data MongoDB 一:入门篇
- Spring+SpringMVC+mybatis入门(环境搭建+crud)
- android 自动登录
- 侧滑栏
- beatPicker使用出现Uncaught ReferenceError: module is not defined
- MYSQL 需要注意的常规问题
- Cent6.3 防火墙配置文件
- Spring Data 与MongoDB 集成一:入门篇(开发环境搭建和简单CRUD)
- 堆和栈的区别
- 常用编码总结
- android:padding和android:margin的区别
- JAVA多线程实现的三种方式
- 浅析JavaScript设计模式——策略模式
- 记忆
- 《合成孔径雷达成像——算法与实现》之【3】仿真图3.2
- [绍棠] iOS10实现推送功能时的注意点和问题总结