4.3MongoDB實(shí)現(xiàn)自增id

MongoDB在數(shù)據(jù)庫(kù)設(shè)計(jì)上和其他關(guān)系數(shù)據(jù)庫(kù)有什么不同,估計(jì)第一個(gè)想到的就是自增ID的實(shí)現(xiàn)。Oracle可以通過(guò)sequence來(lái)實(shí)現(xiàn),mysql和Sqlserver自帶自增id字段。

MongoDB怎么實(shí)現(xiàn)自增id呢?MongoDB官網(wǎng)上也提供了一種實(shí)現(xiàn)的方法,就是自定義一個(gè)獲取自增ID的方法,然后每次插入的時(shí)候就去獲取下一個(gè)ID,再插入到集合中。

下面來(lái)講一下基于java的具體實(shí)現(xiàn),原理就是先獲取序列的值,然后設(shè)置給對(duì)應(yīng)的實(shí)體,代碼如下:

定義序列MongoSequence.java

public class MongoSequence {
    @Id
    private String id;
    private int seq;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public int getSeq() {
        return seq;
    }

    public void setSeq(int seq) {
        this.seq = seq;
    }
}

這是簡(jiǎn)單的java對(duì)象,就是模擬序列的存儲(chǔ)

序列生成工具類MongoAutoidUtil.java

@Component
public class MongoAutoidUtil {
    @Autowired
    MongoTemplate mongo;

    public int getNextSequence(String collectionName) {
        MongoSequence seq = mongo.findAndModify(
                query(where("_id").is(collectionName)),
                new Update().inc("seq", 1),
                options().upsert(true).returnNew(true),
                MongoSequence.class);

        return seq.getSeq();
    }
}

代碼很簡(jiǎn)單,就是根據(jù)傳入的序列名稱獲取下一個(gè)序列值。
通過(guò)findAndModify這個(gè)方法來(lái)保證序列唯一,因?yàn)檫@是一個(gè)原子操作。
這段代碼的原理就是,新建一個(gè)mongoSequence的Collection(如果沒(méi)有才新增),然后根據(jù)傳入的collectionName,根據(jù)_id即主鍵去找,如果有值,則+1,并返回修改后的值,如果沒(méi)有則新增一條記錄,并返回該值。

如果改為關(guān)系數(shù)據(jù)庫(kù),則原理就是這樣,新建一個(gè)表mongoSequence,里面兩個(gè)字段_id,seq,當(dāng)根據(jù)_id來(lái)取值時(shí),如果沒(méi)有記錄,則新增一條記錄,并返回1,如果有記錄,則把seq+1,并返回修改后的記錄。通過(guò)findAndModify來(lái)實(shí)現(xiàn)lock鎖定這一行的目的。

測(cè)試新增

@Test
    public void add() {
        for (int i = 0; i < 10; i++) {  //增加一條記錄
            Article article = new Article();
            article.setId(mongoAutoidUtil.getNextSequence("seq_article"));
            article.setTitle("MongoTemplate的基本使用");
            article.setAuthor("kcy");
            article.setUrl("http://jianshu.com/");
            article.setTags(Arrays.asList("java", "mongodb", "spring"));
            article.setVisitCount(0L);
            article.setAddTime(new Date());
            mongoTemplate.save(article);
        }

        Iterable<Article> articles = articleRepository.findAll();
        articles.forEach(article2 -> {
            System.out.println(article2.toString());
        });
    }

在設(shè)置article的id時(shí)通過(guò)article.setId(mongoAutoidUtil.getNextSequence("seq_article"));來(lái)獲取序列的值,并賦給這個(gè)id。

自增id的實(shí)現(xiàn)和oracle的序列原理基本一致。

源碼下載

[本工程詳細(xì)源碼]
(https://github.com/chykong/java_component/tree/master/chapter4_3_mongodb_autoid)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容