【问题标题】:MongoDB to have auto incrementing Integer Id within a collection using Spring Data MongoMongoDB 使用 Spring Data Mongo 在集合中自动递增 Integer Id
【发布时间】:2017-01-11 07:57:54
【问题描述】:

我在一个域对象@Id private Long id;

Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Cannot autogenerate id of type java.lang.Long for entity of type ...

这可以通过使用字符串作为@Id private String id;来解决

但如果我没有多线程(或妥善处理),也没有分布式 MongoDB 集群,而且我确实希望 Id 更友好,
如何使整数自动递增使用 Spring Data MongoDB 在 Java 中使用 MongoDB Id

使用的版本:

  • MongoDB 3.2
  • javamongodb-driver3.2.2
  • spring-data-mongodb1.9.2.RELEASE

相关:

字符串的当前代码

import org.springframework.data.annotation.Id;

public @lombok.Data class Item {
    @Id private String id;  
    private String name;

}

【问题讨论】:

    标签: java spring mongodb spring-data spring-data-mongodb


    【解决方案1】:

    MongoDB 建议两种方法来处理这种情况:auto-increment-optimistic-loop

    1. 使用计数器集合

    创建一个文档来保存您的序列号

    db.counters.insert(
       {
          _id: "mySequenceName",
          seq: 0
       }
    )
    

    在 mongodb 中创建一个 getNextSequenceNumber javascript 函数

    function getNextSequence() {
       var ret = db.counters.findAndModify(
              {
                query: { _id: mySequenceName },
                update: { $inc: { seq: 1 } },
                new: true
              }
       );
    
       return ret.seq;
    }
    

    在插入文档之前,获取下一个序列号:

    BasicDBObject basicDbObject = new BasicDBObject();
    basicDbObject.append( "$eval" , "getNextSequence()" );
    
    CommandResult result = mongoTemplate.executeCommand(basicDbObject);
    Object seqno = result.get("seq");
    

    插入您的文档

    Mode model...
    model.setId(Long.parseLong(seqno));
    repository.save(model);
    
    1. 乐观循环

    创建自定义 insertDocument mongodb 函数

    另一种方法要求您绕过 spring-data 进行插入。这一切都在 mongodb javascript 函数中完成(您需要创建)。

    该函数将首先检索您正在插入的文档的最大_id:

    var cursor = targetCollection.find( {}, { _id: 1 } ).sort( { _id: -1 } ).limit(1);function insertDocument(doc, targetCollection) {
    
    var seq = cursor.hasNext() ? cursor.next()._id + 1 : 1;
    

    然后,您可以使用序列号插入文档:

    var results = targetCollection.insert(doc);
    

    但是,由于序列号可能已被另一个同时插入使用,因此您需要检查错误,并在需要时重复该过程,这就是整个函数在 while(1) 循环中运行的原因。

    完整的功能:

    function insertDocument(doc, targetCollection) {
        while (1) {
    
            var cursor = targetCollection.find( {}, { _id: 1 } ).sort( { _id: -1 } ).limit(1);
    
            var seq = cursor.hasNext() ? cursor.next()._id + 1 : 1;
    
            doc._id = seq;
    
            var results = targetCollection.insert(doc);
    
            if( results.hasWriteError() ) {
                if( results.writeError.code == 11000 /* dup key */ )
                    continue;
                else
                    print( "unexpected error inserting data: " + tojson( results ) );
            }
    
            break;
        }
    }
    

    调用insertDocument mongodb函数

    现在,您可以从 java 调用 javascript 函数 insertDocument。要使用参数调用 mongo 存储过程,我相信 doEval 可能有用:

    MongoClient mongoClient = new MongoClient();
    DB db = mongoClient.getDB("dbName");
    Model m = new Model(...);
    CommandResult result = db.doEval("insertDocument", model);
    

    【讨论】:

      猜你喜欢
      • 2020-07-19
      • 2019-11-27
      • 2013-08-24
      • 2021-10-05
      • 1970-01-01
      • 2012-12-14
      • 2018-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多