这段时间给朋友做了一个微信小程序,顺便练习一下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。

SpringBoot+mongoDB实现id自增的更多相关文章

  1. SpringBoot+MongoDB实现物流订单系统

    码字不易,点赞收藏,养成习惯!原创作者公众号:bigsai.更多精彩期待与您分享!项目收录在github的MongoDB案例中,文章收录在回车课堂中如果没基础请看看前两篇(墙裂推荐)MongoDB从立 ...

  2. 【第十二章】 springboot + mongodb(复杂查询)

    简单查询:使用自定义的XxxRepository接口即可.(见 第十一章 springboot + mongodb(简单查询)) 复杂查询:使用MongoTemplate以及一些查询条件构建类(Bas ...

  3. 第十二章 springboot + mongodb(复杂查询)

    简单查询:使用自定义的XxxRepository接口即可.(见 第十一章 springboot + mongodb(简单查询)) 复杂查询:使用MongoTemplate以及一些查询条件构建类(Bas ...

  4. mongodb的安装与增删改查

    mongodb是一款分布式的文件存储的数据库,注意这两个词,分布式和文件存储.mongodb支持复制和分片,可以合理的运用空间的大小,也可以达到容灾的目的.另外文件存储也是一个特点,抛弃了传统的表的概 ...

  5. 十四:SpringBoot-配置MongoDB数据库,实现增删改查逻辑

    SpringBoot-配置MongoDB数据库,实现增删改查逻辑 1.MongoDB数据库 1.1 MongoDB简介 1.2 MongoDB特点 2.SpringBoot整合MongoDB 2.1 ...

  6. 【pymongo】mongodb cursor id not valid error

    参考来源: http://stackoverflow.com/questions/10298354/mongodb-cursor-id-not-valid-error http://stackover ...

  7. Oracle 给表添加主键和使ID自增、触发器、创建结构一样的表

    1.关于主键:在建表时指定primary key字句即可:create table test( id number(6) primary key, name varchar2(30));如果是对于已经 ...

  8. phpmyadmin设置id自增(AUTO_INCREMENT)(转)

    phpmyadmin设置id自增(AUTO_INCREMENT)   在A_I 前面打勾:如图 AUTO_INCREMENT =A_I 查看效果  

  9. hibernate解决oracle的id自增?

    以前做SSH项目时,涉及到的数据库是mySQL,只需将bean的配置文件id设为native 就可以实现表id的自增. 现在用到了Oracle,当然知道这样是不行的啦,那么用序列自增? 我在网络上搜索 ...

随机推荐

  1. navicat操作mysql数据库

    1.利用mysql来做ER图 1.1点击模型->新建模型->点击表->新建表,这样就可以了 1.2 建好的ER图->工具 有导出到sql ,有同步到数据库 1.3 建好的表,可 ...

  2. 组合数取mod

    组合数取mod 条件mod是质数,inv 是逆元,fac是阶层: 用于n在10^5左右 maxn=100505: ll fact[maxn],inv[maxn]; ll Pow(ll x,ll n){ ...

  3. Python之路Day05

    字典 字典 -- dict Python的数据结构之一 字典是可变数据类型,无序的 定义 dic = {'key':'Value'} 键值对 字典的作用 存储数据,大大量的,将数据和数据起到关联作用 ...

  4. 修改linux的MAC地址

    命令修改 步骤如下,但不唯一: 1.临时性的修改: ①依次输入以下命令: /sbin/ifconfig eth0 down /sbin/ifconfig eth0 hw ether 00:0C:29: ...

  5. DM9000C网卡驱动程序编写与测试

    一般网卡驱动程序厂商会给我们提供一份模板驱动,我们的工作就是需要根据自己的需要更改这个模板驱动 1.DM9000C的硬件连接 硬件连接图如下所示:它接在S3C2440的BANK4内存控制器上,它只占用 ...

  6. JS高级---函数作为参数使用

    函数作为参数使用 var arr = [1, 100, 20, 200, 40, 50, 120, 10]; //排序 arr.sort(); console.log(arr); 排序---函数作为参 ...

  7. electron聊天室|vue+electron-vue仿微信客户端|electron桌面聊天

    一.项目概况 基于Electron+vue+electron-vue+vuex+Nodejs+vueVideoPlayer+electron-builder等技术仿制微信电脑端界面聊天室实例,实现消息 ...

  8. NOIP做题练习(day5)

    A - 中位数图 题面 题解 先找出题意中的\(b\)所在的位置. 再以这个位置为中心,向右\(for\)一遍有多少个大于/小于该数的数 大于就\(++cs\) 小于就\(--cs\). 因为这个数是 ...

  9. 熬最深的夜喝最劣的酒————浅谈生成器(generator)

    测试(test)def s(): print("stup1") n = "第一步" yield n # 类似于return 但是又不同于 赖克宝,剁一下,跳一下 ...

  10. FIR滤波器工作原理(算法)以及verilog算法实现(包含与IIR的一些对比)

    滤波器在2017年IC前端的笔试中,出现频率十分的高.不论今后是否会涉及,还是要记住一些会比较好.接下来就将从这四个方面来讲解,FIR数字滤波器的工作原理(算法)与verilog实现. ·什么是FIR ...