MongoDB在数据库设计上和其他关系数据库有什么不同,估计第一个想到的就是自增ID的实现。Oracle可以通过sequence来实现,mysql和Sqlserver自带自增id字段。
MongoDB怎么实现自增id呢?MongoDB官网上也提供了一种实现的方法,就是自定义一个获取自增ID的方法,然后每次插入的时候就去获取下一个ID,再插入到集合中。
下面来讲一下基于java的具体实现,原理就是先获取序列的值,然后设置给对应的实体,代码如下:
定义序列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;
}
}
这是简单的java对象,就是模拟序列的存储
序列生成工具类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();
}
}
代码很简单,就是根据传入的序列名称获取下一个序列值。
通过findAndModify
这个方法来保证序列唯一,因为这是一个原子操作。
这段代码的原理就是,新建一个mongoSequence
的Collection(如果没有才新增),然后根据传入的collectionName
,根据_id
即主键去找,如果有值,则+1,并返回修改后的值,如果没有则新增一条记录,并返回该值。
如果改为关系数据库,则原理就是这样,新建一个表mongoSequence
,里面两个字段_id
,seq
,当根据_id
来取值时,如果没有记录,则新增一条记录,并返回1,如果有记录,则把seq
+1,并返回修改后的记录。通过findAndModify
来实现lock
锁定这一行的目的。
测试新增
@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());
});
}
在设置article的id时通过article.setId(mongoAutoidUtil.getNextSequence("seq_article"));
来获取序列的值,并赋给这个id。
自增id的实现和oracle的序列原理基本一致。
源码下载
[本工程详细源码]
(https://github.com/chykong/java_component/tree/master/chapter4_3_mongodb_autoid)