zoukankan      html  css  js  c++  java
  • SpringBoot+mongoDB实现id自增

    这段时间给朋友做了一个微信小程序,顺便练习一下spring boot,虽然项目使用的是JPA+MySQL,但是好奇尝试了一下MongoDB实现自增ID,虽然MongoDB很少有自增ID的需求(在分布式环境中,多个机器同步一个自增ID不但费时且费力,MongoDB从一开始就是设计用来做分布式数据库的,处理多个节点是一个核心要求,而ObjectId在分片环境中要容易生成的多),但是需求是多变的,难免会遇到需要自增的需求。

    MongoDB有默认的ObjectId,是一个12字节的 BSON 类型字符串。按照字节顺序,依次次代表:

    • 4字节:UNIX时间戳
    • 3字节:表示运行MongoDB的机器
    • 2字节:表示生成此_id的进程
    • 3字节:由一个随机数开始的计数器生成的值

    Spring boot中可以使用MongoTemplate操作MongoDB,但是不能自增ID,只能手动实现:

    1).自定义注解用于标识需要自增的Field.

        package com.example.annotation;
    
        import java.lang.annotation.ElementType;
        import java.lang.annotation.Retention;
        import java.lang.annotation.RetentionPolicy;
        import java.lang.annotation.Target;
    
        @Target(ElementType.FIELD)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface AutoIncKey {}
    

    2).创建数据表存储当前的id号

    id的自增进度需要一个数据表存储(只是存储当前id号数据,可以不用数据库而用其他形式)

    @Document(collection = "inc")
    public class IncInfo {
    
        @Id
        private String id;// 主键
    
        @Field
        private String collName;// 需要自增id的集合名称(这里设置为MyDomain)
    
        @Field
        private Integer incId;// 当前自增id值
    
        // 省略getter、setter
    

    3).实现监听类

    监听器用于监听Mongo Event,该类继承AbstractMongoEventListener类,因为我们需要在JAVA对象转换成数据库对象的时候操作id字段实现id自增,所以覆盖onBeforeConvert方法(详见spring-data文档,https://docs.spring.io/spring-data/data-document/docs/current/reference/html/,5.11节)

        package com.example.listener;
    
        import java.lang.reflect.Field;
        import com.example.annotation.AutoIncKey;
        import com.example.domain.MyDomain;
        import com.example.domain.IncInfo;
        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;
        
        @Component
        public class SaveEventListener extends AbstractMongoEventListener<Object>{
            private static final Logger logger= LoggerFactory.getLogger(SaveEventListener.class);
            @Autowired
            private MongoTemplate mongo;
        
            @Override
            public void onBeforeConvert(BeforeConvertEvent<Object> event) {
                logger.info(event.getSource().toString());
                MyDomain source=(MyDomain)event.getSource();
                if (source != null) {
                    ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
                        public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                            ReflectionUtils.makeAccessible(field);
                            // 如果字段添加了我们自定义的AutoIncKey注解
                            if (field.isAnnotationPresent(AutoIncKey.class)) {
                                // 设置自增ID
                                field.set(source, getNextId(source.getClass().getSimpleName()));
                            }
                        }
                    });
                }
        
            }
        
            private Integer getNextId(String collName) {
                Query query = new Query(Criteria.where("collName").is(collName));
                Update update = new Update();
                update.inc("incId", 1);
                FindAndModifyOptions options = new FindAndModifyOptions();
                options.upsert(true);
                options.returnNew(true);
                IncInfo inc= mongo.findAndModify(query, update, options, IncInfo.class);
                return inc.getIncId();
            }
        }
    
    

    4).在我们的对象中id字段上添加注解

        @Id
        @AutoIncKey
        private Integer id=0;
    

    至此就实现了Mongodb的自增id。

  • 相关阅读:
    JSP中<base href="<%=basePath%>">作用
    转 jdk1.5新特性 ConcurrentHashMap
    单例设计模式与类加载顺序详解
    归并排序-java
    插入排序-java
    冒泡排序-java
    选择排序-java
    JS的object数据类型
    JS的事件
    JS的捕捉回车键
  • 原文地址:https://www.cnblogs.com/yzykkpl/p/10356258.html
Copyright © 2011-2022 走看看