public <T> Key<T> merge(T entity, WriteConcern wc) { LinkedHashMap<Object, DBObject> involvedObjects = new LinkedHashMap<Object, DBObject>(); DBObject dbObj = mapr.toDBObject(entity, involvedObjects); Key<T> key = getKey(entity); entity = ProxyHelper.unwrap(entity); Object id = getId(entity); if (id == null) throw new MappingException("Could not get id for " + entity.getClass().getName()); Query<T> query = (Query<T>) createQuery(entity.getClass()).filter(Mapper.ID_KEY, id); // remove (immutable) _id field for update. dbObj.removeField(Mapper.ID_KEY); UpdateResults<T> res = update(query, new BasicDBObject("$set", dbObj), false, false, wc); // check for updated count if we have a gle CommandResult gle = res.getWriteResult().getCachedLastError(); if (gle != null && res.getUpdatedCount() == 0) throw new UpdateException("Not updated: " + gle); postSaveOperations(entity, dbObj, involvedObjects); return key; }
protected <T> WriteResult tryVersionedUpdate( DBCollection dbColl, T entity, DBObject dbObj, WriteConcern wc, DB db, MappedClass mc) { WriteResult wr = null; if (mc.getFieldsAnnotatedWith(Version.class).isEmpty()) return wr; MappedField mfVersion = mc.getFieldsAnnotatedWith(Version.class).get(0); String versionKeyName = mfVersion.getNameToStore(); Long oldVersion = (Long) mfVersion.getFieldValue(entity); long newVersion = VersionHelper.nextValue(oldVersion); dbObj.put(versionKeyName, newVersion); if (oldVersion != null && oldVersion > 0) { Object idValue = dbObj.get(Mapper.ID_KEY); UpdateResults<T> res = update( find((Class<T>) entity.getClass(), Mapper.ID_KEY, idValue) .filter(versionKeyName, oldVersion), dbObj, false, false, wc); wr = res.getWriteResult(); if (res.getUpdatedCount() != 1) throw new ConcurrentModificationException( "Entity of class " + entity.getClass().getName() + " (id='" + idValue + "',version='" + oldVersion + "') was concurrently updated."); } else if (wc == null) wr = dbColl.save(dbObj); else wr = dbColl.save(dbObj, wc); // update the version. mfVersion.setFieldValue(entity, newVersion); return wr; }