springboot整合MongoDB

MongoDB简介:

mongodb属于nosql非关系型数据库中的“文档型数据库”。

非关系型数据库还有键值存储数据库(如redis)、列存储数据库(ru:Neo4j)和图形数据库(Cassandra、Hbase)等

mongodb中基本的概念是数据库、集合和文档(对应mysql的数据库,表和行数据),通常以json格式显示,以bson格式(二进制的json)存储

优势:

1、性能好,因为把一部分数据存储在内存中。

2、扩展性好。

3、高可用。支持故障转移

4、json格式,非常适合存储和查询(不像mysql需要修改“表”结构)

劣势:

1、查询方式比较特别,学习成本高

2、没有事务机制,只支持单文档事务。

3、锁只能提供到集合级别,不能提供到文档级别

4、不支持连表查询

使用场景:

可以把一些经常添加或更新的、表结构多变的,不需要复杂查询的,事务要求不高的,数据量较大的表,

从mysql迁移到mongodb中(因为数据量太大查询会很慢),例如:日志,报表、通知、传感器采集的数据等

开始整合:

1、引入pom


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <version>2.2.4.RELEASE</version>
</dependency>

2、配置文件添加:

#mongodb
spring.data.mongodb.uri=mongodb://localhost:27017/sumengnan

3、创建实体类用@Document注解

package com.sumengnan.test.domain;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

@Document(collection="mongo")
public class Mongo {

    @Id
    private Long id;

    private String size;

    private String color;

    private Double price;
    //getter,setter……
}

4、在Controller注入MongoTemplate就可以使用了,简单保存和查询如下:

           //保存(插入或更新)
             Mongo mongo = new Mongo();
            mongo.setColor("红色"+i);
            mongo.setPrice(123.32d);
            mongo.setSize("12");
            mongoTemplate.save(mongo,"mongo");  //第二个参数为collname     


            //查询
         Query query = new Query();
        query.addCriteria(Criteria.where("color").is("红色"));
        List<Mongo> mongo = mongoTemplate.find(query, Mongo.class, "mongo");//第二个参数为collname
        System.out.println(mongo);

还有其他查询方法:

1、Criteria.where("user").is("sumengnan").and("age").is(24)//and多条件查询
2、Criteria.where("user").is("sumengnan").orOperator(Criteria.where("age").is(24), Criteria.where("sex").exists(true))//or多条件查询
3、Criteria.where("age").in(Arrays.asList(11, 21, 33))//in查询
4、Criteria.where("age").gt(24)//gt数值比较,其他的还有gte, gt, lt, let
5、Criteria.where("user").regex("^sumengnan")//regex正则
6、mongoTemplate.count()//count查询总数
7、Aggregation.newAggregation(Aggregation.group("user").count().as("userCount"))//group分组查询
8、Criteria.where("user").is("sumengnan")).with(Sort.by("age")//Sort排序
9、Criteria.where("user").is("sumengnan")).with(Sort.by("age")).limit(2)//limit取出多少数据(分页)
10、Criteria.where("user").is("sumengnan")).with(Sort.by("age")).skip(2)//skip跳过多少数据(分页)

5、完毕

 

问题: mongodb主键没法自动增长?

解决办法:

原理:建一个sequence表(集合)保存序列值,每次插入数据时,先更新序列值(+1),返回当前序列值,设置给要插入数据的id上即可。

步骤:

1、建一个sequence表(集合)

package com.sumengnan.test.domain;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

@Document(collection = "sequence")
public class Sequence {

    @Id
    private String id;// 主键
    private String collName;// 集合名称,为了区分不同集合的序列值
    private Long seqId;// 序列值

    //getter,setter……
}

2、建一个AutoKey注解

package com.sumengnan.test.domain;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 *自动增长id注解类
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoKey {
}

3、添加一个类继承AbstractMongoEventListener,重写onBeforeConvert方法

package com.sumengnan.config;

import com.sumengnan.test.domain.AutoIncKey;
import com.sumengnan.test.domain.Mongo;
import com.sumengnan.test.domain.Sequence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
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.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;

/**
 * 监听添加操作,并将自增id插入
 */
@Component
public class SaveEventListener<T> extends AbstractMongoEventListener<Object> {

    private static final Logger logger = LoggerFactory.getLogger(SaveEventListener.class);
    @Autowired
    private MongoTemplate mongo;

    /**
     *
     * @param event
     */
    @Override
    public void onBeforeConvert(BeforeConvertEvent<Object> event) {
        T source = (T) event.getSource();
        if (source != null) {
            ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
                @Override
                public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    ReflectionUtils.makeAccessible(field);
                    // 如果字段添加了我们自定义的AutoIncKey注解
                    if (field.isAnnotationPresent(AutoIncKey.class)) {
                        // 设置自增ID
                        try {
                            // 判断当前对象的id是否未空,不为空时不自动生成id
                            Field idField = source.getClass().getDeclaredField(field.getName());//反射获取当前注解的字段,一般是ObjectId
                            idField.setAccessible(true);//设置允许访问private私有属性
                            if (idField.get(source)==null){//获取id的值
                                field.set(source, getNextId(source.getClass().getSimpleName()));
                            }
                        } catch (NoSuchFieldException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }

    }

    private Long getNextId(String collName) {
        Query query = new Query(Criteria.where("collName").is(collName));
        Update update = new Update();
        update.inc("seqId", 1);//把Sequence序列值增加1
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.upsert(true);
        options.returnNew(true);
        Sequence seq = mongo.findAndModify(query, update, options, Sequence.class);//原子操作,更新Sequence序列值,并返回改值
        return seq.getSeqId();
    }
}

4、把AutoKey注解在id要自动增长的实体类上

package com.sumengnan.test.domain;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

@Document(collection="mongo")
public class Mongo {
    @AutoKey
    @Id
    private Long id;

    private String size;

    private String color;

    private Double price;
    //getter,setter……
}

5、当使用mongoTemplate.save()方法时,没有id则自动赋值id为自动增长,否则为更新

 

 

 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值