code: public <RET> RET save(final Object iPojo, final String iClusterName, OPERATION_MODE iMode,
  			final ORecordCallback<? extends Number> iCallback) {
  		checkOpeness();
  
  		if (iPojo == null)
  			return null;
  		else if (OMultiValue.isMultiValue(iPojo)) {
  			// MULTI VALUE OBJECT: STORE SINGLE POJOS
  			for (Object pojo : OMultiValue.getMultiValueIterable(iPojo)) {
  				save(pojo, iClusterName);
  			}
  		} else {
  			OSerializationThreadLocal.INSTANCE.get().clear();
  
  			// GET THE ASSOCIATED DOCUMENT
  			final ODocument record = getRecordByUserObject(iPojo, true);
  			try {
  				record.setInternalStatus(com.orientechnologies.orient.core.db.record.ORecordElement.STATUS.MARSHALLING);
  
  				if (!saveOnlyDirty || record.isDirty()) {
  					// REGISTER BEFORE TO SERIALIZE TO AVOID PROBLEMS WITH CIRCULAR DEPENDENCY
  					// registerUserObject(iPojo, record);
  
  					pojo2Stream(iPojo, record);
  
  					underlying.save(record, iClusterName, iMode, iCallback);
  
  					// RE-REGISTER FOR NEW RECORDS SINCE THE ID HAS CHANGED
  					registerUserObject(iPojo, record);
  				}
  			} finally {
  				record.setInternalStatus(com.orientechnologies.orient.core.db.record.ORecordElement.STATUS.LOADED);
  			}
  		}
  		return (RET) iPojo;
  	}
docs: Saves an object to the database forcing a record cluster where to store it. First checks if the object is new or not. In case
  it's new a new ODocument is created and bound to the object, otherwise the ODocument is retrieved and updated. The object is
  introspected using the Java Reflection to extract the field values. <br/>
  If a multi value (array, collection or map of objects) is passed, then each single object is stored separately.
  
  Before to use the specified cluster a check is made to know if is allowed and figures in the configured and the record is valid
  following the constraints declared in the schema.
  
  @see ORecordSchemaAware#validate()