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

  1. package com.example.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. @Target(ElementType.FIELD)
  7. @Retention(RetentionPolicy.RUNTIME)
  8. public @interface AutoIncKey {}

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

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

  1. @Document(collection = "inc")
  2. public class IncInfo {
  3. @Id
  4. private String id;// 主键
  5. @Field
  6. private String collName;// 需要自增id的集合名称(这里设置为MyDomain)
  7. @Field
  8. private Integer incId;// 当前自增id值
  9. // 省略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节)

  1. package com.example.listener;
  2. import java.lang.reflect.Field;
  3. import com.example.annotation.AutoIncKey;
  4. import com.example.domain.MyDomain;
  5. import com.example.domain.IncInfo;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.data.mongodb.core.FindAndModifyOptions;
  10. import org.springframework.data.mongodb.core.MongoTemplate;
  11. import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
  12. import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
  13. import org.springframework.data.mongodb.core.query.Criteria;
  14. import org.springframework.data.mongodb.core.query.Query;
  15. import org.springframework.data.mongodb.core.query.Update;
  16. import org.springframework.stereotype.Component;
  17. import org.springframework.util.ReflectionUtils;
  18. @Component
  19. public class SaveEventListener extends AbstractMongoEventListener<Object>{
  20. private static final Logger logger= LoggerFactory.getLogger(SaveEventListener.class);
  21. @Autowired
  22. private MongoTemplate mongo;
  23. @Override
  24. public void onBeforeConvert(BeforeConvertEvent<Object> event) {
  25. logger.info(event.getSource().toString());
  26. MyDomain source=(MyDomain)event.getSource();
  27. if (source != null) {
  28. ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
  29. public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
  30. ReflectionUtils.makeAccessible(field);
  31. // 如果字段添加了我们自定义的AutoIncKey注解
  32. if (field.isAnnotationPresent(AutoIncKey.class)) {
  33. // 设置自增ID
  34. field.set(source, getNextId(source.getClass().getSimpleName()));
  35. }
  36. }
  37. });
  38. }
  39. }
  40. private Integer getNextId(String collName) {
  41. Query query = new Query(Criteria.where("collName").is(collName));
  42. Update update = new Update();
  43. update.inc("incId", 1);
  44. FindAndModifyOptions options = new FindAndModifyOptions();
  45. options.upsert(true);
  46. options.returnNew(true);
  47. IncInfo inc= mongo.findAndModify(query, update, options, IncInfo.class);
  48. return inc.getIncId();
  49. }
  50. }

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

  1. @Id
  2. @AutoIncKey
  3. 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. 转载:Cubic interpolation

    https://www.paulinternet.nl/?page=bicubic Cubic interpolation If the values of a function f(x) and i ...

  2. linux网卡

    手动启动 ifup eth0 查询网卡配置信息 vim /etc/udev/rules.d/70-persistent-net.rules 备注:可以修改网卡名称和MAC地址

  3. XPath注入

    XPath基础 XPath 即为 XML 路径语言,是一门在XML文档中查找信息的语言.XPath 基于 XML 的树状结构,有不同类型的节点,包括元素节点,属性节点和文本节点,提供在数据结构树中找寻 ...

  4. 关于pip命令的几点提醒

    pip install xxxxx 总会遇到安装失败,或者下载速度很慢的情况.这是因为从国外安装资源包,造成速度慢,那有咩有国内的源呢,有的. 国内源: 清华:https://pypi.tuna.ts ...

  5. java基础之 类型转换

    一.自动类型转换 1.java中不同类型的数据在计算时,为保证数据的精度,数据的类型会以大容量的类型为主: 2.自动类型转换的排序: char.byte.short -> int -> l ...

  6. pycharm连接mysql5.7

    由于加密方式改变 需要在url后增加 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC

  7. 故障解决 | win10没声音及找不到Realtek高清音频管理器

    重装 win10 系统后,电脑没声音,更新驱动以及万不得已下载驱动精灵都没有解决. 后来发现在“硬件和声音”中没有Realtek高清音频管理器,之后找到解决办法如下: 1. 找到Realtek高清音频 ...

  8. VS调试工具

    F5--启动运行,跳到下一个断点 F10--逐步调试 F11--逐句调试 F10和F11的区别: method(); int a = 1; 当程序运行到如上面的method方法时,按F10会直接跳到下 ...

  9. HTML学习(13)区块元素和内联元素

    HTML 区块元素 大多数 HTML 元素被定义为块级元素或内联元素. 块级元素在浏览器显示时,通常会以新行来开始(和结束). 实例: <h1>, <p>, <ul> ...

  10. thinkphp 接收文件并处理

    html前台文件,上传到控制器,thinkphp处理它 前台 <form action="{:url('product/brand_addcl')}" enctype=&qu ...