近期对两个应用进行改造,在上线过程中出现一系列问题(其中一部分是由于ObjectId误区导致的)
Query query = new Query();
if (id != null)
{
query.addCriteria(Criteria.where("_id").gt(id));
}
query.with(new Sort(Sort.Direction.ASC, "_id"));
Comparator comparator = new Comparator()
{
@Override
public int compare(DBObject o1, DBObject o2)
{
return ((ObjectId)o1.get("_id")).compareTo((ObjectId)o2.get("_id"));
}
};
PriorityQueue queue = new PriorityQueue(200,comparator);
public WriteResult insert(List list, com.mongodb.WriteConcern concern, DBEncoder encoder ){
if (concern == null) {
throw new IllegalArgumentException("Write concern can not be null");
}
return insert(list, true, concern, encoder);
}
protected WriteResult insert(List list, boolean shouldApply , com.mongodb.WriteConcern concern, DBEncoder encoder ){
if (encoder == null)
encoder = DefaultDBEncoder.FACTORY.create();
if ( willTrace() ) {
for (DBObject o : list) {
trace( "save: " + _fullNameSpace + " " + JSON.serialize( o ) );
}
}
if ( shouldApply ){
for (DBObject o : list) {
apply(o);
_checkObject(o, false, false);
Object id = o.get("_id");
if (id instanceof ObjectId) {
((ObjectId) id).notNew();
}
}
}
WriteResult last = null;
int cur = 0;
int maxsize = _mongo.getMaxBsonObjectSize();
while ( cur < list.size() ) {
OutMessage om = OutMessage.insert( this , encoder, concern );
for ( ; cur < list.size(); cur++ ){
DBObject o = list.get(cur);
om.putObject( o );
// limit for batch insert is 4 x maxbson on server, use 2 x to be safe
if ( om.size() > 2 * maxsize ){
cur++;
break;
}
}
last = _connector.say( _db , om , concern );
}
return last;
}
自动添加ObjectId的操作
/**
* calls {@link DBCollection#apply(com.mongodb.DBObject, boolean)} with ensureID=true
* @param o DBObject
to which to add fields
* @return the modified parameter object
*/
public Object apply( DBObject o ){
return apply( o , true );
}
/**
* calls {@link DBCollection#doapply(com.mongodb.DBObject)}, optionally adding an automatic _id field
* @param jo object to add fields to
* @param ensureID whether to add an _id
field
* @return the modified object o
*/
public Object apply( DBObject jo , boolean ensureID ){
Object id = jo.get( "_id" );
if ( ensureID && id == null ){
id = ObjectId.get();
jo.put( "_id" , id );
}
doapply( jo );
return id;
}
可以看到,mongoDB的驱动包中是会自动添加ObjectId的。
public WriteResult save( DBObject jo, WriteConcern concern ){
if ( checkReadOnly( true ) )
return null;
_checkObject( jo , false , false );
Object id = jo.get( "_id" );
if ( id == null || ( id instanceof ObjectId && ((ObjectId)id).isNew() ) ){
if ( id != null && id instanceof ObjectId )
((ObjectId)id).notNew();
if ( concern == null )
return insert( jo );
else
return insert( jo, concern );
}
DBObject q = new BasicDBObject();
q.put( "_id" , id );
if ( concern == null )
return update( q , jo , true , false );
else
return update( q , jo , true , false , concern );
}
DBObject update = new BasicDBObject("$inc", new BasicDBObject("counter", 1));
DBObject query = new BasicDBObject("_id", key);
DBObject result = getMongoTemplate().getCollection(collectionName).findAndModify(query, update);
if (result == null)
{
DBObject doc = new BasicDBObject();
doc.put("counter", 1L);
doc.put("_id", key);
// insert(collectionName, doc);
getMongoTemplate().save(doc, collectionName);
return 1L;
}
return (Long) result.get("counter");