MongoDB
MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是可以应用于各种规模的企业、各个行业以及各类应用程序的开源数据库。基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成,MongoDB是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。MongoDB对于关系型数据库里的表,但是集合中没有列、行和关系概念,这体现了模式自由的特点。
MySql |
MongoDB |
数据库 |
数据库 |
表 |
集合 |
行 |
文档 |
记录 |
字段 |
开发环境
IDEA、Maven、SpringBoot2.0.4、Jdk1.8、MongoDB4.0、MongoDB Compass Community、PostMan
配置开始
- Maven 相关配置
在pox.xml文件中添加spring-boot-starter-data-mongodb引用
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
|
- 资源文件yml配置
笔者这里使用yml配置方式,配置时要注意缩进!!!!
1 2 3 4 5 6 7 8 9 10 11
| server: port: 8031
spring: application: name: spirng-boot-mongodb data: mongodb: host: localhost port: 27017 database: test
|
- 创建实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import org.springframework.data.annotation.Id; import java.util.Date;
public class Book { @Id private String id; private Integer price; private String name; private String info; private String publish; private Date createTime; private Date updateTime;
|
- 创建service类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
| import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; 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 org.springframework.stereotype.Service;
import java.util.Date; import java.util.List;
@Service public class MongoDbService { private static final Logger logger = LoggerFactory.getLogger(MongoDbService.class);
@Autowired private MongoTemplate mongoTemplate;
public String saveObj(Book book) { logger.info("--------------------->[MongoDB save start]"); book.setCreateTime(new Date()); book.setUpdateTime(new Date()); mongoTemplate.save(book); return "添加成功"; }
public List<Book> findAll() { logger.info("--------------------->[MongoDB find start]"); return mongoTemplate.findAll(Book.class); }
public Book getBookById(String id) { logger.info("--------------------->[MongoDB find start]"); Query query = new Query(Criteria.where("_id").is(id)); return mongoTemplate.findOne(query, Book.class); }
public Book getBookByName(String name) { logger.info("--------------------->[MongoDB find start]"); Query query = new Query(Criteria.where("name").is(name)); return mongoTemplate.findOne(query, Book.class); }
public String updateBook(Book book) { logger.info("--------------------->[MongoDB update start]"); Query query = new Query(Criteria.where("_id").is(book.getId())); Update update = new Update().set("publish", book.getPublish()) .set("info", book.getInfo()) .set("updateTime", new Date()); mongoTemplate.updateFirst(query, update, Book.class);
return "success"; }
public String deleteBook(Book book) { logger.info("--------------------->[MongoDB delete start]"); mongoTemplate.remove(book); return "success"; }
public String deleteBookById(String id) { logger.info("--------------------->[MongoDB delete start]"); Book book = getBookById(id); deleteBook(book); return "success"; } }
|
- controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import com.example.mqdemo.mongo.Book; import com.example.mqdemo.mongo.MongoDbService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*;
import java.util.List;
/*** * @author zhengql * @date 2018/8/9 10:38 */ @RestController public class BaseController {
@Autowired private MongoDbService mongoDbService;
@PostMapping("/mongo/save") public String saveObj(@RequestBody Book book) {return mongoDbService.saveObj(book);}
@GetMapping("/mongo/findAll") public List<Book> findAll() {return mongoDbService.findAll();}
@GetMapping("/mongo/findOne") public Book findOne(@RequestParam String id) {return mongoDbService.getBookById(id);}
@GetMapping("/mongo/findOneByName") public Book findOneByName(@RequestParam String name) {return mongoDbService.getBookByName(name);}
@PostMapping("/mongo/update") public String update(@RequestBody Book book) {return mongoDbService.updateBook(book);}
@PostMapping("/mongo/delOne") public String delOne(@RequestBody Book book) {return mongoDbService.deleteBook(book);}
@GetMapping("/mongo/delById") public String delById(@RequestParam String id) {return mongoDbService.deleteBookById(id);} }
|
- 运行测试
启动项目,打开postman开始接口调试,可以看到成功添加book对象。返回添加成功。
打开MongoDB Compass Community,连接本地MongoDB,可以看到刚才添加的信息。
其他接口这里就不一一测试了。
优化使用
完成以上配置,我们springBoot集成MongoDB环境基本已经搭建好了。
但是在使用中会发现一个问题,假如要对数据库操作多个对象,那岂不是每一个对象Service都需要写一套增删查改的方法。
为了解决这一问题我们可以封装一个通用的操作类来提高效率。
创建MongoDbDao类如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
| import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; 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.Method; import java.util.List;
/** * 描述: * mongoDB基础方法封装 * * @author zhengql * @date 2018/8/9 14:01 */ public abstract class MongoDbDao<T> {
protected Logger logger = LoggerFactory.getLogger(MongoDbDao.class);
/** * 反射获取泛型类型 * * @return */ protected abstract Class<T> getEntityClass();
@Autowired private MongoTemplate mongoTemplate;
/*** * 保存一个对象 * @param t */ public void save(T t) { logger.info("-------------->MongoDB save start"); this.mongoTemplate.save(t); }
/*** * 根据id从几何中查询对象 * @param id * @return */ public T queryById(Integer id) { Query query = new Query(Criteria.where("_id").is(id)); logger.info("-------------->MongoDB find start"); return this.mongoTemplate.findOne(query, this.getEntityClass()); }
/** * 根据条件查询集合 * * @param object * @return */ public List<T> queryList(T object) { Query query = getQueryByObject(object); logger.info("-------------->MongoDB find start"); return mongoTemplate.find(query, this.getEntityClass()); }
/** * 根据条件查询只返回一个文档 * * @param object * @return */ public T queryOne(T object) { Query query = getQueryByObject(object); logger.info("-------------->MongoDB find start"); return mongoTemplate.findOne(query, this.getEntityClass()); }
/*** * 根据条件分页查询 * @param object * @param start 查询起始值 * @param size 查询大小 * @return */ public List<T> getPage(T object, int start, int size) { Query query = getQueryByObject(object); query.skip(start); query.limit(size); logger.info("-------------->MongoDB queryPage start"); return this.mongoTemplate.find(query, this.getEntityClass()); }
/*** * 根据条件查询库中符合条件的记录数量 * @param object * @return */ public Long getCount(T object) { Query query = getQueryByObject(object); logger.info("-------------->MongoDB Count start"); return this.mongoTemplate.count(query, this.getEntityClass()); }
/*** * 删除对象 * @param t * @return */ public int delete(T t) { logger.info("-------------->MongoDB delete start"); return (int) this.mongoTemplate.remove(t).getDeletedCount(); }
/** * 根据id删除 * * @param id */ public void deleteById(Integer id) { Criteria criteria = Criteria.where("_id").is(id); if (null != criteria) { Query query = new Query(criteria); T obj = this.mongoTemplate.findOne(query, this.getEntityClass()); logger.info("-------------->MongoDB deleteById start"); if (obj != null) { this.delete(obj); } } }
/*MongoDB中更新操作分为三种 * 1:updateFirst 修改第一条 * 2:updateMulti 修改所有匹配的记录 * 3:upsert 修改时如果不存在则进行添加操作 * */
/** * 修改匹配到的第一条记录 * @param srcObj * @param targetObj */ public void updateFirst(T srcObj, T targetObj){ Query query = getQueryByObject(srcObj); Update update = getUpdateByObject(targetObj); logger.info("-------------->MongoDB updateFirst start"); this.mongoTemplate.updateFirst(query,update,this.getEntityClass()); }
/*** * 修改匹配到的所有记录 * @param srcObj * @param targetObj */ public void updateMulti(T srcObj, T targetObj){ Query query = getQueryByObject(srcObj); Update update = getUpdateByObject(targetObj); logger.info("-------------->MongoDB updateFirst start"); this.mongoTemplate.updateMulti(query,update,this.getEntityClass()); }
/*** * 修改匹配到的记录,若不存在该记录则进行添加 * @param srcObj * @param targetObj */ public void updateInsert(T srcObj, T targetObj){ Query query = getQueryByObject(srcObj); Update update = getUpdateByObject(targetObj); logger.info("-------------->MongoDB updateInsert start"); this.mongoTemplate.upsert(query,update,this.getEntityClass()); }
/** * 将查询条件对象转换为query * * @param object * @return * @author Jason */ private Query getQueryByObject(T object) { Query query = new Query(); String[] fileds = getFiledName(object); Criteria criteria = new Criteria(); for (int i = 0; i < fileds.length; i++) { String filedName = (String) fileds[i]; Object filedValue = getFieldValueByName(filedName, object); if (filedValue != null) { criteria.and(filedName).is(filedValue); } } query.addCriteria(criteria); return query; }
/** * 将查询条件对象转换为update * * @param object * @return * @author Jason */ private Update getUpdateByObject(T object) { Update update = new Update(); String[] fileds = getFiledName(object); for (int i = 0; i < fileds.length; i++) { String filedName = (String) fileds[i]; Object filedValue =getFieldValueByName(filedName, object); if (filedValue != null) { update.set(filedName, filedValue); } } return update; }
/*** * 获取对象属性返回字符串数组 * @param o * @return */ private static String[] getFiledName(Object o) { Field[] fields = o.getClass().getDeclaredFields(); String[] fieldNames = new String[fields.length];
for (int i = 0; i < fields.length; ++i) { fieldNames[i] = fields[i].getName(); }
return fieldNames; }
/*** * 根据属性获取对象属性值 * @param fieldName * @param o * @return */ private static Object getFieldValueByName(String fieldName, Object o) { try { String e = fieldName.substring(0, 1).toUpperCase(); String getter = "get" + e + fieldName.substring(1); Method method = o.getClass().getMethod(getter, new Class[0]); return method.invoke(o, new Object[0]); } catch (Exception var6) { return null; } } }
|
我们将mongoDB常用的CURD操作封装为通用的父类,然后在不同的业务场景下继承该类,通过泛型和反射获取到正在操作的实体类。
比如我们可以将之前的Book实体类的CURD类进行改造
创建BookMongoDbDao类继承MongoDbDao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import org.springframework.stereotype.Repository;
/** * 描述: * * @author zhengql * @date 2018/8/9 20:46 */ @Repository public class BookMongoDbDao extends MongoDbDao<Book> { @Override protected Class<Book> getEntityClass() { return Book.class; } }
|
接下来我们可以改造Book的Service类
原始版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Service public class BookMongoDbService { private static final Logger logger = LoggerFactory.getLogger(BookMongoDbService.class);
@Autowired private MongoTemplate mongoTemplate;
/** * 保存对象 * * @param book * @return */ public String saveObj(Book book) { logger.info("--------------------->[MongoDB save start]"); book.setCreateTime(new Date()); book.setUpdateTime(new Date()); mongoTemplate.save(book); return "添加成功"; }
//其他操作方法...... }
|
改造后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Service public class BookMongoDbService { private static final Logger logger = LoggerFactory.getLogger(BookMongoDbService.class);
@Autowired private MongoTemplate mongoTemplate;
@Autowired private BookMongoDbDao bookMongoDbDao;
/** * 保存对象 * * @param book * @return */ public String saveObj(Book book) { logger.info("--------------------->[MongoDB save start]"); book.setCreateTime(new Date()); book.setUpdateTime(new Date()); mongoTemplate.save(book); return "添加成功"; }
public String saveObj2(Book book) { book.setCreateTime(new Date()); book.setUpdateTime(new Date()); bookMongoDbDao.save(book); return "添加成功"; } }
|
改造后的saveObj2方法的效果与以前的一致,但是大大的提高了开发效率。不需要重复的编写CURD的方法。
总结
通过以上的配置已经完成springboot与mongoDB集成环境的初步搭建,当然了MongoDB在springboot中的使用不仅于此,还有更多的功能和更优雅的使用方式等待着我们去发掘。