什么是NoSQL?
NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
优点:
缺点:
MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
它的特点是高性能、易部署、易使用,存储数据非常方便。主要功能特性有:
MongoDB 的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)和传统的RDBMS 系统(具有丰富的功能)之间架起一座桥梁,它集两者的优势于一身。
根据官方网站的描述,Mongo 适用于以下场景。
MongoDB 的使用也会有一些限制,例如,它不适合于以下几个地方。
该例子演示的功能有如下
1、mongodb事务
具体实现可查看之前的文章springboot实战之mongodb事务支持
2、mongodb 自增ID
其核心主要是重写AbstractMongoEventListener,这个类可以监听MongoDB的生命周期。其监听回调的方法如下
核心代码
@Componentpublic class GeneratedValueMongodbEventListener extends AbstractMongoEventListener<Object> {
@Autowired private MongoTemplate mongoTemplate;
/** * 调用MongoTemplate的insert、insertList和save操作,在通过MongoConverter将对象转换为文档之前的处理。 * @param event */ @Override public void onBeforeConvert(BeforeConvertEvent<Object> event) {
Object source = event.getSource(); if(source != null) { ReflectionUtils.doWithFields(source.getClass(), field -> { ReflectionUtils.makeAccessible(field); if (field.isAnnotationPresent(GeneratedValue.class)) { //设置自增ID boolean hasDocumentAnnotation = source.getClass().isAnnotationPresent(Document.class); String collectionName = source.getClass().getSimpleName(); if(hasDocumentAnnotation){ Document document = source.getClass().getAnnotation(Document.class); collectionName = document.value(); }
field.set(source, getNextId(collectionName)); } }); } }
/** * 获取下一个自增ID * @param collName 集合名 * @return */ private Long getNextId(String collName) { Query query = new Query(Criteria.where("collName").is(collName)); Update update = new Update(); update.inc("seqId", 1); FindAndModifyOptions options = new FindAndModifyOptions(); options.upsert(true); options.returnNew(true); SequenceId seqId = mongoTemplate.findAndModify(query, update, options, SequenceId.class); return seqId.getSeqId(); }
具体完整代码可以查看如下链接
http://1t.click/ajgz
3、mongodb 字段驼峰和mongdb属性下划线映射
通过重写org.springframework.data.mapping.model.FieldNamingStrategy来实现,其代码如下
//参考FieldNamingStrategy的其他实现//userName->user_namepublic class CamelCaseFieldNamingStrategy implements FieldNamingStrategy { @Override public String getFieldName(PersistentProperty<?> property) { List<String> parts = ParsingUtils.splitCamelCaseToLower(property.getName()); StringBuilder sb = new StringBuilder(); Iterator it = parts.iterator(); if(it.hasNext()){ sb.append(it.next().toString()); while (it.hasNext()){ sb.append("_"); sb.append(it.next().toString()); } } return sb.toString(); }}
要使其字段命名策略生效,还需得更改mongodb默认的字段命名策略规则,其更换代码如下
@Bean public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, BeanFactory beanFactory) { DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context); // Don't save _class to mongo mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null)); if("SNAKE_CASE".equalsIgnoreCase(fieldNamingStrategy)) { context.setFieldNamingStrategy(new CamelCaseFieldNamingStrategy()); }
return mappingConverter; }
4、mongodb 自定义转换器实现
通过实现org.springframework.core.convert.converter.Converter接口,其例子代码如下
// Direction: MongoDB -> Java@ReadingConverterpublic class GenderReadConverter implements Converter<Integer, Gender> {
@Override public Gender convert(Integer integer) {
return Gender.getValue(integer); }}
// Direction: Java -> MongoDB@WritingConverterpublic class GenderWriteConverter implements Converter<Gender,Integer> {
@Override public Integer convert(Gender gender) {
return gender.getValue(); }}
要使其转换规则生效,还需做如下配置
@Bean public MongoCustomConversions mongoCustomConversions() { return new MongoCustomConversions(Arrays.asList(new GenderWriteConverter(),new GenderReadConverter())); }
@Bean public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, BeanFactory beanFactory) { DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context); // Don't save _class to mongo mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null)); mappingConverter.setCustomConversions(mongoCustomConversions());
return mappingConverter; }
5、mongodb 分页
其分页主要拿Ryan Miao这位博主在github上已经实现的代码,不过该代码在带查询条件分页时,会有bug,我这边做了调整,然后这位博主针对分页,也写了一篇文章,其链接如下,感兴趣的朋友可以看下
https://www.cnblogs.com/woshimrf/p/mongodb-pagenation-performance.html
springboot与mongodb的整合就写这么多了,nosql其含义不是no sql,并不是为了来取代传统关系型数据库,而是not only sql,是作为传统关系型数据库的补充,因为在某些业务场景下,nosql是无法满足业务要求的,比如强事务要求场景
https://www.runoob.com/mongodb/nosql.html https://baike.baidu.com/item/mongodb https://baike.baidu.com/item/NoSQL
MONGO 生命周期
https://www.cnblogs.com/vana/p/10860106.html
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-mongodb