MongoDb 设置自增ID,舍弃 _id

(一)了解ObjectId

   MongoDB的文档固定是使用“_id”作为主键的,它可以是任何类型的,默认是个ObjectId对象(在Java中则表现为字符串),那么为什么MongoDB没有采用其他比较常规的做法(比如MySql的自增主键),而是采用了ObjectId的形式来实现?别着急,咱们看看ObjectId的生成方式便可知悉。

ObjectId使用12字节的存储空间,每个字节两位十六进制数字,是一个24位的字符串。由于看起来很长,不少人会觉得难以处理,其实不然。ObjectId是由客户端生成的,按照如下方式生成:
在这里插入图片描述

  • 前4位是一个从标准纪元开始的时间戳,是一个int类别,只不过从十进制转换为了十六进制。这意味着这4个字节隐含了文档的创建时间,将会带来一些有用的属性。并且时间戳处于字符的最前面,同时意味着ObjectId大致会按照插入顺序进行排序,这对于某些方面起到很大作用,如作为索引提高搜索效率等等。使用时间戳还有一个好处是,某些客户端驱动可以通过ObjectId解析出该记录是何时插入的,这也解答了我们平时快速连续创建多个Objectid时,会发现前几位数字很少发现变化的现实,因为使用的是当前时间,很多用户担心要对服务器进行时间同步,其实这个时间戳的真实值并不重要,只要其总不停增加就好。
  • 接下来的3个字节,是所在主机的唯一标识符,一般是机器主机名的散列值,这样就确保了不同主机生成不同的机器hash值,确保在分布式中不造成冲突,这也就是在同一台机器生成的objectid中间的字符串都是一模一样的原因。
  • 上面的机器字节是为了确保在不同机器产生的ObjectId不冲突,而PID就是为了在同一台机器不同的mongodb进程产生了ObjectId不冲突。
  • 前面的9个字节是保证了一秒内不同机器不同进程生成ObjectId不冲突,最后的3个字节是一个自动增加的计数器,用来确保在同一秒内产生的ObjectId也不会冲突,允许256的3次方等于16777216条记录的唯一性。

   因此,MongoDB不使用自增主键,而是使用ObjectId。在分布式环境中,多个机器同步一个自增ID不但费时且费力,MongoDB从一开始就是设计用来做分布式数据库的,处理多个节点是一个核心要求,而ObjectId在分片环境中要容易生成的多。

(二)手动实现自增ID

定义一个存储主键ID的集合:

@Document(collection = "sequence")
public class SeqInfo implements Serializable {
    @Id
    private String id;//主键
    private int seqId;//序列值  BySeq中的主键

定义操作的实体类:

@Document(collection = "byseq")
public class BySeq implements Serializable {
    @Id
    public int id;
    @Field
    public String name;
    @Field
    public int age;

定义一个自增ID的类:

@Component
public class MongodbSaveEventListener{

    public int getNextSequence(String collectionName) {
        SeqInfo seq = MongoDBClientUtil.mongoTemplate().findAndModify(
                //找不见则创建  id:collectionName
                query(where("id").is(collectionName)),
                new Update().inc("seqId", 1),
                options().upsert(true).returnNew(true),
                SeqInfo.class);

        return seq.getSeqId();
    }
}

实验操作:

@ApiOperation(value = "Mongogodb 新增(自增ID)", notes = "Mongogodb 新增(自增ID)")
    @RequestMapping(value = "/mongodbInsertByIncId", method = RequestMethod.POST)
    public List<BySeq> mongodbInsertByIncId() {
        List<BySeq> list = new ArrayList<>();
        BySeq bySeq = new BySeq();
        bySeq.setId(new MongodbSaveEventListener().getNextSequence("byseq"));
        bySeq.setName("LJ");
        bySeq.setAge(14);
        BySeq insert = MongoDBClientUtil.mongoTemplate().insert(bySeq);
        BySeq bySeq1 = new BySeq();
        bySeq1.setId(new MongodbSaveEventListener().getNextSequence("byseq"));
        bySeq1.setName("连喜灯");
        bySeq1.setAge(45);
        BySeq insert1 = MongoDBClientUtil.mongoTemplate().insert(bySeq1);
        BySeq bySeq2 = new BySeq();
        bySeq2.setId(new MongodbSaveEventListener().getNextSequence("byseq"));
        bySeq2.setName("李会政");
        bySeq2.setAge(56);
        BySeq insert2 = MongoDBClientUtil.mongoTemplate().insert(bySeq2);
        list.add(insert);
        list.add(insert1);
        list.add(insert2);
        /*BySeq insert = MongoDBClientUtil.mongoTemplate().insert(bySeq);
        BySeq insert1 = MongoDBClientUtil.mongoTemplate().insert(bySeq1);
        BySeq insert2 = MongoDBClientUtil.mongoTemplate().insert(bySeq2);*/
        return list;
    }

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值