【Mongodb】后台主键_id自增(Java版本)

ObjectId的选择

创建MongoDB文档时,如果没有赋值ID,系统会自动帮你创建一个,通常会在客户端由驱动程序完成。得到的ObjectId类似于这种

 

 

ObjectId使用12字节的存储空间,每个字节两位十六进制数字,是一个24位的字符串。其含义分别代表时间戳、机器码、PID、计数器。时间戳是文档创建时的时间,只是从十进制转化成了十六进制。机器码是生成文档主机的ID,为了区分多主机而生成的。PID则是区分同主机下不同mongoDB进程产生的,同样防止冲突。前面的9个字节是保证了一秒内不同机器不同进程生成ObjectId不冲突,最后的3个字节是一个自动增加的计数器,用来确保在同一秒内产生的ObjectId也不会冲突,允许256的3次方等于16777216条记录的唯一性。

 

 显然系统生成的ObjectID已经很严谨了,但是在选择系统创建还是程序创建id上,经过网上查找的一些资料,得到的结论是尽量采用程序创建的方式,速度、可读性、可维护性都要强于系统创建。

虽然ObjectId 设计成轻量型的,易于生成,但是毕竟生成的时候还是产生开销。在客户端生成体现了MongoDB 的设计理念:能从服务器端转移到驱动程序来做的事,就尽量转移。这种理念背后的原因是,即便是像MongoDB 这样的可扩展数据库,扩展应用层也要比扩展数据库层容易得多。将事务交由客户端来处理,就减轻了数据库扩展的负担。

在客户端生成ObjectId,驱动程序能够提供更加丰富的API。例如,驱动程序可以有自己的insert 方法,可以返回生成的ObjectId,也可以直接将其插入文档。如果驱动程序允许服务器生成ObjectId,那么将需要单独的查询,以确定插入的文档中的"_id" 值。

设计思路

创建一个序列计数的文档,记录所有文档的名称和序列值,序列值设置默认0,每次进行插入操作的时候,序列值+1,作为本次操作的id。

程序实现

开发环境:IntelliJ IDEA+JAVA8+SpringBoot

1 创建序列计数类,用于存储各文档以及文档序列值。

 

 2 自定义注解

 

 3 定义实体类,自己要实现自增的实体类(get、set),与文档一一对应

 

 4 定义监听类SaveEventListener。重写save方法。在每次存储时候进行主键自增

 

 5.然后测试(中间的111113删除掉了)

           

注意

如果根据主键查询的话要进行转化:

 

 

 

到此,MongoDB的主键自增就完成了。

 

总结
经过测试,以上流程没有问题,会得到期望的结果,但是有以下几点需要注意:

(1)为什么我在Student类中为主键赋了一个默认值0L?

答:我在此自增方式原作者文章中发现这么一句,“注意自增ID的类型不要定义成Long这种包装类,mongotemplate的源码里面对主键ID的类型有限制”。测试后发现,如果ID定义为原生类型确实是没有问题的。当ID定义为包装类的情况下,如果在onBeforeConvert方法之前没有给ID设置值,是会报错的,我猜测可能是因为内部转换类型时如果ID是空值而无法转换引起的,因此,我赋了一个默认值,这样就不会报错了,包装类也可以使用(不过这样好像跟原生类型就没什么区别了,没什么意义)。

(2)这个监听器会不会影响修改操作?

答:测试发现,不会影响,水平有限,本人也不知作何解释,不要打我……

(3)这种方式会有并发问题吗?

答:不会的!根据官方文档说明,findAndModify一个原子性操作,不过有这么一句“When the findAndModify command includes the upsert: true option and the query field(s) is not uniquely indexed, the command could insert a document multiple times in certain circumstances.”,大概意思是说当查询和更新两个操作都存在时,如果查询的字段没有唯一索引的话,该命令可能会在某些情况下更新/插入 文档多次,参考链接:戳我戳我。以上演示的是只存储了集合所对应的实体类的短名称,短名称是会重复的,所以这种方法不妥,还是记录长名称吧

 


菜鸟程序员,若有需修正之处,望指正~
 
参考文章:[代码与酒]https://blog.csdn.net/qq_16313365/article/details/72781469

 

菜鸟程序媛,若有需修正之处,望指正~

WeChat/QQ:2463105280

【顺便说一下湖南有需要报考学历、证件的可以咨询我,保证毕业拿证,学信网可查学籍!给娃赚点尿不湿~】

posted @ 2020-02-24 18:14  阿迪di  阅读(1485)  评论(0编辑  收藏  举报
Title