【转】https://github.com/xbwen/xbwen.github.io/wiki/MongoDB-Java-Driver%E4%B8%AD%E7%9A%84%E5%86%99%E6%93%8D%E4%BD%9C%E7%AD%96%E7%95%A5
1、WriteConcern
当Java程序往MongoDB中写数据的时候,可以通过设置WriteConcern参数,来控制写操作策略。
WriteConcern是MongoDB Java Driver提供的一个类,它提供了若干常量,其中最常用的2个如下:
ACKNOWLEDGED——Java Driver会等待MongoDB Server确认写操作完成。
UNACKNOWLEDGED——Java Driver把写操作请求发往MongoDB Server,然后立刻返回,不管MongoDB Server是否执行了该写操作。
显然,通过ACKNOWLEDGED能知道写操作是否成功,但执行写入操作会比较耗时;UNACKNOWLEDGED写入速度会非常快,但无法知道写入是否成功。
2、全局默认配置
接下来,我们结合BuguMongo中的代码,看看WriteConcern在实际中是如何使用的。
MongoDB Java Driver默认使用ACKNOWLEDGED,这个默认值是在MongoClientOptions中定义的:
public class MongoClientOptions {
…
private WriteConcern writeConcern = WriteConcern.ACKNOWLEDGED;
…
}
也就是说,MongoDB Java Driver默认所有的写操作都是需要确认再返回的。如果你要改变这个全局的配置,可以在建立BuguConnection连接的时候,赋值一个自定义的MongoClientOptions。例如:
MongoClientOptions myOptions = MongoClientOptions.builder().writeConcern(WriteConcern.UNACKNOWLEDGED).build();
BuguConnection conn = BuguConnection.getInstance();
conn.setOptions(myOptions);
conn.connect("192.168.0.100", 27017, "mydb", "username", "password");
3、BuguDao中的WriteConcern
然而,在一个项目中,使用同一个写入策略,是不太现实的。我们往往需要经常变换写入策略。别担心,BuguDao提供了setWriteConcern()方法,你可以针对不同的Collection设定不同的写入策略,而且可以随时改变。
如果不进行设置的话,BuguDao默认使用的是ACKNOWLEDGED。
我们可以进行一个比较实验,分别使用ACKNOWLEDGED和UNACKNOWLEDGED,往MongoDB中写入1万条数据,看看耗时相差多少。
@Entity
public class Foo extends SimpleEntity {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
实验1:
BuguDao dao = new BuguDao(Foo.class);
long begin = System.currentTimeMillis();
for(int i=0; i<10000; i++){
Foo foo = new Foo();
foo.setContent("abcdefg" + i);
dao.save(foo);
}
long end = System.currentTimeMillis();
System.out.println(end - begin);
这里,我们不对WriteConcern进行设置,而是使用默认的ACKNOWLEDGED。代码执行3次,在我的笔记本电脑上,输出的结果分别是:
55007, 55503, 54066
实验2:
BuguDao dao = new BuguDao(Foo.class);
//设置WriteConcern为UNACKNOWLEDGED,而不是默认的ACKNOWLEDGED
dao.setWriteConcern(WriteConcern.UNACKNOWLEDGED);
long begin = System.currentTimeMillis();
for(int i=0; i<10000; i++){
Foo foo = new Foo();
foo.setContent("abcdefg" + i);
dao.save(foo);
}
long end = System.currentTimeMillis();
System.out.println(end - begin);
代码执行3次,在我的笔记本电脑上,输出的结果分别是:
1736, 2636, 1470
可以看出,写入的速度快了很多。
4、写操作的返回值
上面的实验中,我们忽略了dao.save(foo)的返回值。实际上,BuguDao中的所有写操作,返回值都是WriteResult,而不是void。例如:
public WriteResult save(T t)
如果你使用的WriteConcern是UNACKNOWLEDGED,那么WriteResult是没有任何用处的。但如果你使用的是ACKNOWLEDGED,那么可以从WriteResult中获得写操作的结果,例如:操作是否成功,总共写了多少条数据,等等。