docs: public int insert(DatabaseType databaseType, DatabaseConnection databaseConnection, T data, ObjectCache objectCache)
  			throws SQLException {
  		KeyHolder keyHolder = null;
  		if (idField != null) {
  			boolean assignId;
  			if (idField.isAllowGeneratedIdInsert() && !idField.isObjectsFieldValueDefault(data)) {
  				assignId = false;
  			} else {
  				assignId = true;
  			}
  			if (idField.isSelfGeneratedId() && idField.isGeneratedId()) {
  				if (assignId) {
  					idField.assignField(connectionSource, data, idField.generateId(), false, objectCache);
  				}
  			} else if (idField.isGeneratedIdSequence() && databaseType.isSelectSequenceBeforeInsert()) {
  				if (assignId) {
  					assignSequenceId(databaseConnection, data, objectCache);
  				}
  			} else if (idField.isGeneratedId()) {
  				if (assignId) {
  					// get the id back from the database
  					keyHolder = new KeyHolder(idField.getColumnName());
  				}
  			} else {
  				// the id should have been set by the caller already
  			}
  		}
  
  		try {
  			// implement {@link DatabaseField#foreignAutoCreate()}, need to do this _before_ getFieldObjects() below
  			if (tableInfo.isForeignAutoCreate()) {
  				for (FieldType fieldType : tableInfo.getFieldTypes()) {
  					if (!fieldType.isForeignAutoCreate()) {
  						continue;
  					}
  					// get the field value
  					Object foreignObj = fieldType.extractRawJavaFieldValue(data);
  					if (foreignObj != null && fieldType.getForeignIdField().isObjectsFieldValueDefault(foreignObj)) {
  						fieldType.createWithForeignDao(foreignObj);
  					}
  				}
  			}
  
  			Object[] args = getFieldObjects(data);
  			Object versionDefaultValue = null;
  			// implement {@link DatabaseField#version()}
  			if (versionFieldTypeIndex >= 0 && args[versionFieldTypeIndex] == null) {
  				// if the version is null then we need to initialize it before create
  				FieldType versionFieldType = argFieldTypes[versionFieldTypeIndex];
  				versionDefaultValue = versionFieldType.moveToNextValue(null);
  				args[versionFieldTypeIndex] = versionFieldType.convertJavaFieldToSqlArgValue(versionDefaultValue);
  			}
  
  			int rowC;
  			try {
  				rowC = databaseConnection.insert(statement, args, argFieldTypes, keyHolder);
  			} catch (SQLException e) {
  				// NOTE: don't log full exception here
  				logger.debug("insert data with statement '{}' and {} args, threw exception: {}", statement, args.length,
  						e);
  				if (args.length > 0) {
  					// need to do the (Object) cast to force args to be a single object
  					logger.trace("insert arguments: {}", (Object) args);
  				}
  				throw e;
  			}
  			logger.debug("insert data with statement '{}' and {} args, changed {} rows", statement, args.length, rowC);
  			if (args.length > 0) {
  				// need to do the (Object) cast to force args to be a single object
  				logger.trace("insert arguments: {}", (Object) args);
  			}
  			if (rowC > 0) {
  				if (versionDefaultValue != null) {
  					argFieldTypes[versionFieldTypeIndex].assignField(connectionSource, data, versionDefaultValue, false,
  							null);
  				}
  				if (keyHolder != null) {
  					// assign the key returned by the database to the object's id field after it was inserted
  					Number key = keyHolder.getKey();
  					if (key == null) {
  						// may never happen but let's be careful out there
  						throw new SQLException(
  								"generated-id key was not set by the update call, maybe a schema mismatch between entity and database table?");
  					}
  					if (key.longValue() == 0L) {
  						// sanity check because the generated-key returned is 0 by default, may never happen
  						throw new SQLException(
  								"generated-id key must not be 0 value, maybe a schema mismatch between entity and database table?");
  					}
  					assignIdValue(data, key, "keyholder", objectCache);
  				}
  				/*
  				 * If we have a cache and if all of the foreign-collection fields have been assigned then add to cache.
  				 * However, if one of the foreign collections has not be assigned then don't add it to the cache.
  				 */
  				if (objectCache != null && foreignCollectionsAreAssigned(tableInfo.getForeignCollections(), data)) {
  					Object id = idField.extractJavaFieldValue(data);
  					objectCache.put(clazz, id, data);
  				}
  			}
  
  			return rowC;
  		} catch (SQLException e) {
  			throw SqlExceptionUtil.create("Unable to run insert stmt on object " + data + ": " + statement, e);
  		}
  	}