diff --git a/typo3/sysext/core/Classes/DataHandling/RecordFieldTransformer.php b/typo3/sysext/core/Classes/DataHandling/RecordFieldTransformer.php
index 607e595acb3c68671a50526501ac309ec7023ce4..a3d4e05cce847d07f19175c75180815f9268c1e4 100644
--- a/typo3/sysext/core/Classes/DataHandling/RecordFieldTransformer.php
+++ b/typo3/sysext/core/Classes/DataHandling/RecordFieldTransformer.php
@@ -88,7 +88,7 @@ readonly class RecordFieldTransformer
 
         // type=file needs to be handled before RelationalFieldTypeInterface
         if ($fieldInformation instanceof FileFieldType) {
-            if ($fieldInformation->getRelationshipType()->isToOne()) {
+            if ($fieldInformation->getRelationshipType()->hasOne()) {
                 return new RecordPropertyClosure(
                     function () use ($rawRecord, $fieldInformation, $context): ?FileReference {
                         $fileReference = $this->relationResolver->resolveFileReferences($rawRecord, $fieldInformation, $context)[0] ?? null;
@@ -108,7 +108,7 @@ readonly class RecordFieldTransformer
             /** @var RecordFactory $recordFactory */
             // @todo This method is called by RecordFactory -> instantiating the factory here again shows, that those classes should actually be somehow belong together.
             $recordFactory = GeneralUtility::makeInstance(RecordFactory::class);
-            if ($fieldInformation->getRelationshipType()->isToOne()) {
+            if ($fieldInformation->getRelationshipType()->hasOne()) {
                 return new RecordPropertyClosure(
                     function () use ($rawRecord, $fieldInformation, $context, $recordFactory): ?RecordInterface {
                         $recordData = $this->relationResolver->resolve($rawRecord, $fieldInformation, $context)[0] ?? null;
diff --git a/typo3/sysext/core/Classes/Schema/Capability/FieldCapability.php b/typo3/sysext/core/Classes/Schema/Capability/FieldCapability.php
index 21c8e355724e13c3c00928c7fa08230a02edf834..61bdfa3634212dbbb91a14ebfa6582df61c723c6 100644
--- a/typo3/sysext/core/Classes/Schema/Capability/FieldCapability.php
+++ b/typo3/sysext/core/Classes/Schema/Capability/FieldCapability.php
@@ -44,4 +44,9 @@ final readonly class FieldCapability implements SchemaCapabilityInterface
     {
         return $this->field;
     }
+
+    public function __toString(): string
+    {
+        return $this->getFieldName();
+    }
 }
diff --git a/typo3/sysext/core/Classes/Schema/Capability/SystemInternalFieldCapability.php b/typo3/sysext/core/Classes/Schema/Capability/SystemInternalFieldCapability.php
index 6feada11c52c89efbba53137dcec779d1aee4bbb..fdfca48d3ae11db3288689559cd5902f57593ab4 100644
--- a/typo3/sysext/core/Classes/Schema/Capability/SystemInternalFieldCapability.php
+++ b/typo3/sysext/core/Classes/Schema/Capability/SystemInternalFieldCapability.php
@@ -36,4 +36,9 @@ final readonly class SystemInternalFieldCapability implements SchemaCapabilityIn
     {
         return $this->fieldName;
     }
+
+    public function __toString(): string
+    {
+        return $this->getFieldName();
+    }
 }
diff --git a/typo3/sysext/core/Classes/Schema/Field/DateTimeFieldType.php b/typo3/sysext/core/Classes/Schema/Field/DateTimeFieldType.php
index e20639f638f52156a4529e59c89029cc6fd801a4..18e1824b83c12611a69298c58bf2a61ff3ebc21d 100644
--- a/typo3/sysext/core/Classes/Schema/Field/DateTimeFieldType.php
+++ b/typo3/sysext/core/Classes/Schema/Field/DateTimeFieldType.php
@@ -17,6 +17,8 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Core\Schema\Field;
 
+use TYPO3\CMS\Core\Database\Query\QueryHelper;
+
 /**
  * @internal This is an experimental implementation and might change until TYPO3 v13 LTS
  */
@@ -34,7 +36,7 @@ final readonly class DateTimeFieldType extends AbstractFieldType implements Fiel
 
     public function getPersistenceType(): ?string
     {
-        return $this->configuration['dbtype'] ?? null;
+        return in_array($this->configuration['dbType'] ?? null, QueryHelper::getDateTimeTypes(), true) ? $this->configuration['dbType'] : null;
     }
 
     public function isNullable(): bool
diff --git a/typo3/sysext/core/Classes/Schema/RelationshipType.php b/typo3/sysext/core/Classes/Schema/RelationshipType.php
index 541112fe4273c7a76bcca9debd04d4e64c4b878d..7bc2ce621cc90a7e8b1c7860e37e8d0ebdc73a43 100644
--- a/typo3/sysext/core/Classes/Schema/RelationshipType.php
+++ b/typo3/sysext/core/Classes/Schema/RelationshipType.php
@@ -72,11 +72,16 @@ enum RelationshipType: string
         return self::Undefined;
     }
 
-    public function isToOne(): bool
+    public function hasOne(): bool
     {
         return in_array($this, [self::OneToOne, self::ManyToOne], true);
     }
 
+    public function hasMany(): bool
+    {
+        return in_array($this, [self::ManyToMany, self::OneToMany, self::List], true);
+    }
+
     public function isSingularRelationship(): bool
     {
         return in_array($this, [self::OneToOne, self::ManyToOne, self::OneToMany, self::List], true);
diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMapFactory.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMapFactory.php
index 9814a5feef75e6f06296564e59f1e249eed90e3e..f435e084234b1a01f60824c91f4a8797c070456e 100644
--- a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMapFactory.php
+++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMapFactory.php
@@ -17,10 +17,13 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Extbase\Persistence\Generic\Mapper;
 
-use TYPO3\CMS\Core\Database\Query\QueryHelper;
 use TYPO3\CMS\Core\DataHandling\TableColumnType;
+use TYPO3\CMS\Core\Schema\Field\DateTimeFieldType;
+use TYPO3\CMS\Core\Schema\Field\FieldTypeInterface;
+use TYPO3\CMS\Core\Schema\Field\FolderFieldType;
+use TYPO3\CMS\Core\Schema\Field\RelationalFieldTypeInterface;
+use TYPO3\CMS\Core\Schema\RelationshipType;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedRelationException;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\Relation;
 use TYPO3\CMS\Extbase\Reflection\ClassSchema\Exception\NoPropertyTypesException;
 use TYPO3\CMS\Extbase\Reflection\ClassSchema\Exception\NoSuchPropertyException;
@@ -29,15 +32,15 @@ use TYPO3\CMS\Extbase\Reflection\ReflectionService;
 /**
  * @internal only to be used within Extbase, not part of TYPO3 Core API.
  */
-class ColumnMapFactory
+readonly class ColumnMapFactory
 {
     public function __construct(
-        private readonly ReflectionService $reflectionService
+        private ReflectionService $reflectionService
     ) {}
 
-    public function create(string $columnName, array $columnDefinition, string $propertyName, string $className): ColumnMap
+    public function create(FieldTypeInterface $field, string $propertyName, string $className): ColumnMap
     {
-        $columnMap = GeneralUtility::makeInstance(ColumnMap::class, $columnName);
+        $columnMap = GeneralUtility::makeInstance(ColumnMap::class, $field->getName());
         try {
             $property = $this->reflectionService->getClassSchema($className)->getProperty($propertyName);
             $nonProxyPropertyTypes = $property->getFilteredTypes([$property, 'filterLazyLoadingProxyAndLazyObjectStorage']);
@@ -59,105 +62,70 @@ class ColumnMapFactory
         } catch (NoSuchPropertyException|NoPropertyTypesException $e) {
             [$type, $elementType] = [null, null];
         }
-        $columnMap = $this->setType($columnMap, $columnDefinition['config']);
-        $columnMap = $this->setRelations($columnMap, $columnDefinition['config'], $type, $elementType);
-        return $this->setDateTimeStorageFormat($columnMap, $columnDefinition['config']);
-    }
-
-    /**
-     * Set the table column type
-     */
-    protected function setType(ColumnMap $columnMap, array $columnConfiguration): ColumnMap
-    {
-        // todo: this method should only be called with proper arguments which means that the TCA integrity check should
-        // todo: take place outside this method.
-
-        $tableColumnType = $columnConfiguration['type'] ?? null;
-        $columnMap->setType(TableColumnType::tryFrom($tableColumnType) ?? TableColumnType::INPUT);
+        // @todo Why type "input" - shouldn't we better throw an exception here?
+        $columnMap->setType(TableColumnType::tryFrom($field->getType()) ?? TableColumnType::INPUT);
+        if ($field instanceof DateTimeFieldType) {
+            $columnMap->setDateTimeStorageFormat($field->getPersistenceType());
+        }
+        $columnMap = $this->setRelations($columnMap, $field, $type, $elementType);
         return $columnMap;
     }
 
     /**
      * This method tries to determine the type of relation to other tables and sets it based on
      * the $TCA column configuration
-     *
-     * @param ColumnMap $columnMap The column map
-     * @param array|null $columnConfiguration The column configuration from $TCA
      */
-    protected function setRelations(ColumnMap $columnMap, ?array $columnConfiguration, ?string $type, ?string $elementType): ColumnMap
+    protected function setRelations(ColumnMap $columnMap, FieldTypeInterface $field, ?string $type, ?string $elementType): ColumnMap
     {
-        if (!isset($columnConfiguration)) {
+        $columnConfiguration = $field->getConfiguration();
+        if ($field instanceof FolderFieldType
+            && !in_array((string)($columnConfiguration['relationship'] ?? ''), ['oneToOne', 'manyToOne'], true)
+            && (!isset($columnConfiguration['maxitems']) || $columnConfiguration['maxitems'] > 1)
+        ) {
+            $columnMap->setTypeOfRelation(Relation::HAS_MANY);
+            return $columnMap;
+        }
+
+        if ($field instanceof RelationalFieldTypeInterface === false) {
             return $columnMap;
         }
 
-        if (isset($columnConfiguration['MM'])) {
-            return $this->setManyToManyRelation($columnMap, $columnConfiguration);
+        if ($field->getRelationshipType() === RelationshipType::ManyToMany) {
+            return $this->setManyToManyRelation($columnMap, $field);
         }
 
         if ($elementType !== null) {
-            return $this->setOneToManyRelation($columnMap, $columnConfiguration);
+            return $this->setOneToManyRelation($columnMap, $field);
         }
 
         if ($type !== null && strpbrk($type, '_\\') !== false) {
             // @todo: check the strpbrk function call. Seems to be a check for Tx_Foo_Bar style class names
-            return $this->setOneToOneRelation($columnMap, $columnConfiguration);
+            return $this->setOneToOneRelation($columnMap, $field);
         }
 
-        if (
-            isset($columnConfiguration['type'], $columnConfiguration['renderType'])
-            && $columnConfiguration['type'] === 'select'
+        $columnConfiguration = $field->getConfiguration();
+        // @todo we should get rid of the "maxitems" and "renderType" cases here and rely purely on
+        //       the evaluated relationship type -> to be consistent with all non extbase components.
+        if ($field->getRelationshipType()->hasMany()
             && (
-                $columnConfiguration['renderType'] !== 'selectSingle'
-                || (isset($columnConfiguration['maxitems']) && $columnConfiguration['maxitems'] > 1)
+                !$field->isType(TableColumnType::GROUP, TableColumnType::SELECT)
+                || ($field->isType(TableColumnType::GROUP) && (!isset($columnConfiguration['maxitems']) || $columnConfiguration['maxitems'] > 1))
+                || ($field->isType(TableColumnType::SELECT) && (($columnConfiguration['renderType'] ?? '') !== 'selectSingle' || (int)($columnConfiguration['maxitems'] ?? 0) > 1))
             )
         ) {
             $columnMap->setTypeOfRelation(Relation::HAS_MANY);
             return $columnMap;
         }
 
-        if (
-            isset($columnConfiguration['type']) && ($columnConfiguration['type'] === 'group' || $columnConfiguration['type'] === 'folder')
-            && (!isset($columnConfiguration['maxitems']) || $columnConfiguration['maxitems'] > 1)
-        ) {
-            $columnMap->setTypeOfRelation(Relation::HAS_MANY);
-            return $columnMap;
-        }
-
-        return $columnMap;
-    }
-
-    /**
-     * Sets datetime storage format based on $TCA column configuration.
-     *
-     * @param ColumnMap $columnMap The column map
-     * @param array|null $columnConfiguration The column configuration from $TCA
-     */
-    protected function setDateTimeStorageFormat(ColumnMap $columnMap, ?array $columnConfiguration = null): ColumnMap
-    {
-        // todo: this method should only be called with proper arguments which means that the TCA integrity check should
-        // todo: take place outside this method.
-
-        if ($columnMap->getType() === TableColumnType::DATETIME
-            && in_array($columnConfiguration['dbType'] ?? '', QueryHelper::getDateTimeTypes(), true)
-        ) {
-            $columnMap->setDateTimeStorageFormat($columnConfiguration['dbType']);
-        }
-
         return $columnMap;
     }
 
     /**
-     * This method sets the configuration for a 1:1 relation based on
-     * the $TCA column configuration
-     *
-     * @param ColumnMap $columnMap The column map
-     * @param array|null $columnConfiguration The column configuration from $TCA
+     * This method sets the configuration for a 1:1 relation based on the $TCA column configuration
      */
-    protected function setOneToOneRelation(ColumnMap $columnMap, ?array $columnConfiguration = null): ColumnMap
+    protected function setOneToOneRelation(ColumnMap $columnMap, FieldTypeInterface $field): ColumnMap
     {
-        // todo: this method should only be called with proper arguments which means that the TCA integrity check should
-        // todo: take place outside this method.
-
+        $columnConfiguration = $field->getConfiguration();
         $columnMap->setTypeOfRelation(Relation::HAS_ONE);
         // check if foreign_table is set, which usually won't be the case for type "group" fields
         if (!empty($columnConfiguration['foreign_table'])) {
@@ -177,16 +145,11 @@ class ColumnMapFactory
      * This method sets the configuration for a 1:n relation based on
      * the $TCA column configuration
      *
-     * @param ColumnMap $columnMap The column map
-     * @param array|null $columnConfiguration The column configuration from $TCA
-     *
      * @internal
      */
-    public function setOneToManyRelation(ColumnMap $columnMap, ?array $columnConfiguration = null): ColumnMap
+    public function setOneToManyRelation(ColumnMap $columnMap, FieldTypeInterface $field): ColumnMap
     {
-        // todo: this method should only be called with proper arguments which means that the TCA integrity check should
-        // todo: take place outside this method.
-
+        $columnConfiguration = $field->getConfiguration();
         $columnMap->setTypeOfRelation(Relation::HAS_MANY);
         // check if foreign_table is set, which usually won't be the case for type "group" fields
         if (!empty($columnConfiguration['foreign_table'])) {
@@ -204,44 +167,30 @@ class ColumnMapFactory
     }
 
     /**
-     * This method sets the configuration for a m:n relation based on
-     * the $TCA column configuration
-     *
-     * @param ColumnMap $columnMap The column map
-     * @param array|null $columnConfiguration The column configuration from $TCA
-     * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedRelationException
+     * This method sets the configuration for a m:n relation based on the $TCA column configuration
      */
-    protected function setManyToManyRelation(ColumnMap $columnMap, ?array $columnConfiguration = null): ColumnMap
+    protected function setManyToManyRelation(ColumnMap $columnMap, FieldTypeInterface $field): ColumnMap
     {
-        // todo: this method should only be called with proper arguments which means that the TCA integrity check should
-        // todo: take place outside this method.
-
-        if (isset($columnConfiguration['MM'])) {
-            $columnMap->setTypeOfRelation(Relation::HAS_AND_BELONGS_TO_MANY);
-            // check if foreign_table is set, which usually won't be the case for type "group" fields
-            if (!empty($columnConfiguration['foreign_table'])) {
-                $columnMap->setChildTableName($columnConfiguration['foreign_table']);
-            }
-            // todo: don't update column map if value(s) isn't/aren't set.
-            $columnMap->setRelationTableName($columnConfiguration['MM']);
-            if (isset($columnConfiguration['MM_match_fields']) && is_array($columnConfiguration['MM_match_fields'])) {
-                $columnMap->setRelationTableMatchFields($columnConfiguration['MM_match_fields']);
-            }
-            // todo: don't update column map if value(s) isn't/aren't set.
-            if (!empty($columnConfiguration['MM_opposite_field'])) {
-                $columnMap->setParentKeyFieldName('uid_foreign');
-                $columnMap->setChildKeyFieldName('uid_local');
-                $columnMap->setChildSortByFieldName('sorting_foreign');
-            } else {
-                $columnMap->setParentKeyFieldName('uid_local');
-                $columnMap->setChildKeyFieldName('uid_foreign');
-                $columnMap->setChildSortByFieldName('sorting');
-            }
+        $columnConfiguration = $field->getConfiguration();
+        $columnMap->setTypeOfRelation(Relation::HAS_AND_BELONGS_TO_MANY);
+        // check if foreign_table is set, which usually won't be the case for type "group" fields
+        if ($columnConfiguration['foreign_table'] ?? false) {
+            $columnMap->setChildTableName($columnConfiguration['foreign_table']);
+        }
+        // todo: don't update column map if value(s) isn't/aren't set.
+        $columnMap->setRelationTableName($columnConfiguration['MM']);
+        if (isset($columnConfiguration['MM_match_fields']) && is_array($columnConfiguration['MM_match_fields'])) {
+            $columnMap->setRelationTableMatchFields($columnConfiguration['MM_match_fields']);
+        }
+        // todo: don't update column map if value(s) isn't/aren't set.
+        if (!empty($columnConfiguration['MM_opposite_field'])) {
+            $columnMap->setParentKeyFieldName('uid_foreign');
+            $columnMap->setChildKeyFieldName('uid_local');
+            $columnMap->setChildSortByFieldName('sorting_foreign');
         } else {
-            // todo: this else part is actually superfluous because \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory::setRelations
-            // todo: only calls this method if $columnConfiguration['MM'] is set.
-
-            throw new UnsupportedRelationException('The given information to build a many-to-many-relation was not sufficient. Check your TCA definitions. mm-relations with IRRE must have at least a defined "MM" or "foreign_selector".', 1268817963);
+            $columnMap->setParentKeyFieldName('uid_local');
+            $columnMap->setChildKeyFieldName('uid_foreign');
+            $columnMap->setChildSortByFieldName('sorting');
         }
         return $columnMap;
     }
diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapFactory.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapFactory.php
index 69b858d85b3f120921dfc62967ea282028027955..4578e017b5cdb867be22a611475557507e2769fa 100644
--- a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapFactory.php
+++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapFactory.php
@@ -19,6 +19,8 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic\Mapper;
 
 use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
+use TYPO3\CMS\Core\Schema\Capability\TcaSchemaCapability;
+use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
 use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
@@ -66,6 +68,8 @@ class DataMapFactory implements SingletonInterface
 
     private ColumnMapFactory $columnMapFactory;
 
+    private TcaSchemaFactory $tcaSchemaFactory;
+
     protected string $baseCacheIdentifier;
 
     public function __construct(
@@ -74,6 +78,7 @@ class DataMapFactory implements SingletonInterface
         CacheManager $cacheManager,
         ClassesConfiguration $classesConfiguration,
         ColumnMapFactory $columnMapFactory,
+        TcaSchemaFactory $tcaSchemaFactory,
         string $baseCacheIdentifier
     ) {
         $this->reflectionService = $reflectionService;
@@ -82,6 +87,7 @@ class DataMapFactory implements SingletonInterface
         $this->dataMapCache = $this->cacheManager->getCache('extbase');
         $this->classesConfiguration = $classesConfiguration;
         $this->columnMapFactory = $columnMapFactory;
+        $this->tcaSchemaFactory = $tcaSchemaFactory;
         $this->baseCacheIdentifier = $baseCacheIdentifier;
     }
 
@@ -147,13 +153,12 @@ class DataMapFactory implements SingletonInterface
         $dataMap = GeneralUtility::makeInstance(DataMap::class, $className, $tableName, $recordType, $subclasses);
         $dataMap = $this->addMetaDataColumnNames($dataMap, $tableName);
 
-        foreach ($this->getColumnsDefinition($tableName) as $columnName => $columnDefinition) {
+        foreach ($this->tcaSchemaFactory->get($tableName)->getFields() as $columnName => $columnDefinition) {
             $propertyName = $fieldNameToPropertyNameMapping[$columnName]
                 ?? GeneralUtility::underscoredToLowerCamelCase($columnName);
             $dataMap->addColumnMap(
                 $propertyName,
                 $this->columnMapFactory->create(
-                    $columnName,
                     $columnDefinition,
                     $propertyName,
                     $className
@@ -183,62 +188,55 @@ class DataMapFactory implements SingletonInterface
         return $tableName;
     }
 
-    /**
-     * Returns the TCA columns array of the specified table
-     *
-     * @param string $tableName An optional table name to fetch the columns definition from
-     * @return array The TCA columns definition
-     */
-    protected function getColumnsDefinition(string $tableName): array
-    {
-        return is_array($GLOBALS['TCA'][$tableName]['columns'] ?? null) ? $GLOBALS['TCA'][$tableName]['columns'] : [];
-    }
-
     protected function addMetaDataColumnNames(DataMap $dataMap, string $tableName): DataMap
     {
-        $controlSection = $GLOBALS['TCA'][$tableName]['ctrl'] ?? null;
-        if ($controlSection === null) {
+        if (!$this->tcaSchemaFactory->has($tableName)) {
             return $dataMap;
         }
+        $schema = $this->tcaSchemaFactory->get($tableName);
         $dataMap->setPageIdColumnName('pid');
-        if (isset($controlSection['tstamp'])) {
-            $dataMap->setModificationDateColumnName($controlSection['tstamp']);
+        if ($schema->hasCapability(TcaSchemaCapability::UpdatedAt)) {
+            $dataMap->setModificationDateColumnName((string)$schema->getCapability(TcaSchemaCapability::UpdatedAt));
         }
-        if (isset($controlSection['crdate'])) {
-            $dataMap->setCreationDateColumnName($controlSection['crdate']);
+        if ($schema->hasCapability(TcaSchemaCapability::CreatedAt)) {
+            $dataMap->setCreationDateColumnName((string)$schema->getCapability(TcaSchemaCapability::CreatedAt));
         }
-        if (isset($controlSection['delete'])) {
-            $dataMap->setDeletedFlagColumnName($controlSection['delete']);
+        if ($schema->hasCapability(TcaSchemaCapability::SoftDelete)) {
+            $dataMap->setDeletedFlagColumnName((string)$schema->getCapability(TcaSchemaCapability::SoftDelete));
         }
-        if (isset($controlSection['languageField'])) {
-            $dataMap->setLanguageIdColumnName($controlSection['languageField']);
-        }
-        if (isset($controlSection['transOrigPointerField'])) {
-            $dataMap->setTranslationOriginColumnName($controlSection['transOrigPointerField']);
+        if ($schema->hasCapability(TcaSchemaCapability::Language)) {
+            $languageCapability = $schema->getCapability(TcaSchemaCapability::Language);
+            $dataMap->setLanguageIdColumnName($languageCapability->getLanguageField()->getName());
+            $dataMap->setTranslationOriginColumnName($languageCapability->getTranslationOriginPointerField()->getName());
+            if ($languageCapability->hasDiffSourceField()) {
+                $dataMap->setTranslationOriginDiffSourceName($languageCapability->getDiffSourceField()->getName());
+            }
         }
-        if (isset($controlSection['transOrigDiffSourceField'])) {
-            $dataMap->setTranslationOriginDiffSourceName($controlSection['transOrigDiffSourceField']);
+        if ($schema->getSubSchemaDivisorField() !== null) {
+            $dataMap->setRecordTypeColumnName($schema->getSubSchemaDivisorField()->getName());
         }
-        if (isset($controlSection['type'])) {
-            $dataMap->setRecordTypeColumnName($controlSection['type']);
+        if ($schema->hasCapability(TcaSchemaCapability::RestrictionRootLevel)) {
+            // @todo Evaluate if this is correct. We currently have to use canExistOnPages() to keep previous
+            //       behaviour, which is (bool)$rootlevel, so treating "-1" and "1" as TURE, and only 0 als FALSE.
+            $dataMap->setRootLevel($schema->getCapability(TcaSchemaCapability::RestrictionRootLevel)->canExistOnPages());
         }
-        if (isset($controlSection['rootLevel'])) {
-            $dataMap->setRootLevel($controlSection['rootLevel']);
+        if (isset($schema->getRawConfiguration()['is_static'])) {
+            $dataMap->setIsStatic($schema->getRawConfiguration()['is_static']);
         }
-        if (isset($controlSection['is_static'])) {
-            $dataMap->setIsStatic($controlSection['is_static']);
+        if ($schema->hasCapability(TcaSchemaCapability::RestrictionDisabledField)) {
+            $dataMap->setDisabledFlagColumnName((string)$schema->getCapability(TcaSchemaCapability::RestrictionDisabledField));
         }
-        if (isset($controlSection['enablecolumns']['disabled'])) {
-            $dataMap->setDisabledFlagColumnName($controlSection['enablecolumns']['disabled']);
+        if ($schema->hasCapability(TcaSchemaCapability::RestrictionStartTime)) {
+            $dataMap->setDisabledFlagColumnName((string)$schema->getCapability(TcaSchemaCapability::RestrictionStartTime));
         }
-        if (isset($controlSection['enablecolumns']['starttime'])) {
-            $dataMap->setStartTimeColumnName($controlSection['enablecolumns']['starttime']);
+        if ($schema->hasCapability(TcaSchemaCapability::RestrictionEndTime)) {
+            $dataMap->setDisabledFlagColumnName((string)$schema->getCapability(TcaSchemaCapability::RestrictionEndTime));
         }
-        if (isset($controlSection['enablecolumns']['endtime'])) {
-            $dataMap->setEndTimeColumnName($controlSection['enablecolumns']['endtime']);
+        if ($schema->hasCapability(TcaSchemaCapability::RestrictionUserGroup)) {
+            $dataMap->setDisabledFlagColumnName((string)$schema->getCapability(TcaSchemaCapability::RestrictionUserGroup));
         }
-        if (isset($controlSection['enablecolumns']['fe_group'])) {
-            $dataMap->setFrontEndUserGroupColumnName($controlSection['enablecolumns']['fe_group']);
+        if ($schema->hasCapability(TcaSchemaCapability::RestrictionDisabledField)) {
+            $dataMap->setDisabledFlagColumnName((string)$schema->getCapability(TcaSchemaCapability::RestrictionDisabledField));
         }
         return $dataMap;
     }
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/Example.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/Example.php
index 79bfec7b923a8ce5ef27be15a84f3a0201f15ab1..2af05a5f2911318c7da8c5c2e535a7bead7384ff 100644
--- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/Example.php
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/Example.php
@@ -29,6 +29,9 @@ class Example extends AbstractEntity
     protected ?\DateTime $uninitializedDateTimeProperty;
     protected \DateTime $uninitializedMandatoryDateTimeProperty;
     protected ?\DateTime $initializedDateTimeProperty = null;
+    protected ?\DateTime $initializedDateTimePropertyDate = null;
+    protected ?\DateTime $initializedDateTimePropertyDatetime = null;
+    protected ?\DateTime $initializedDateTimePropertyTime = null;
     protected ?CustomDateTime $customDateTime = null;
     public $unknownType;
     public Enum\StringBackedEnum $stringBackedEnum;
@@ -116,6 +119,36 @@ class Example extends AbstractEntity
         $this->initializedDateTimeProperty = $initializedDateTimeProperty;
     }
 
+    public function getInitializedDateTimePropertyDate(): ?\DateTime
+    {
+        return $this->initializedDateTimePropertyDate;
+    }
+
+    public function setInitializedDateTimePropertyDate(?\DateTime $initializedDateTimePropertyDate): void
+    {
+        $this->initializedDateTimePropertyDate = $initializedDateTimePropertyDate;
+    }
+
+    public function getInitializedDateTimePropertyDatetime(): ?\DateTime
+    {
+        return $this->initializedDateTimePropertyDatetime;
+    }
+
+    public function setInitializedDateTimePropertyDatetime(?\DateTime $initializedDateTimePropertyDatetime): void
+    {
+        $this->initializedDateTimePropertyDatetime = $initializedDateTimePropertyDatetime;
+    }
+
+    public function getInitializedDateTimePropertyTime(): ?\DateTime
+    {
+        return $this->initializedDateTimePropertyTime;
+    }
+
+    public function setInitializedDateTimePropertyTime(?\DateTime $initializedDateTimePropertyTime): void
+    {
+        $this->initializedDateTimePropertyTime = $initializedDateTimePropertyTime;
+    }
+
     public function getCustomDateTime(): ?CustomDateTime
     {
         return $this->customDateTime;
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Configuration/TCA/tx_testdatamapper_domain_model_example.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Configuration/TCA/tx_testdatamapper_domain_model_example.php
index 68adf7331f0775bb0ab31351002edcd2c3a8282d..86d5faa70035392a12134f8657164b7632f4de30 100644
--- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Configuration/TCA/tx_testdatamapper_domain_model_example.php
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Configuration/TCA/tx_testdatamapper_domain_model_example.php
@@ -43,6 +43,24 @@ return [
                 'type' => 'datetime',
             ],
         ],
+        'initialized_date_time_property_date' => [
+            'config' => [
+                'type' => 'datetime',
+                'dbType' => 'date',
+            ],
+        ],
+        'initialized_date_time_property_datetime' => [
+            'config' => [
+                'type' => 'datetime',
+                'dbType' => 'datetime',
+            ],
+        ],
+        'initialized_date_time_property_time' => [
+            'config' => [
+                'type' => 'datetime',
+                'dbType' => 'time',
+            ],
+        ],
         'custom_date_time' => [
             'config' => [
                 'type' => 'datetime',
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/ColumnMapFactoryTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/ColumnMapFactoryTest.php
index d849d6da1fa058a8f0d8806e85e8e857b5fb99ba..7083e0859a7c7056aee99809d923764463a33748 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/ColumnMapFactoryTest.php
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/ColumnMapFactoryTest.php
@@ -20,6 +20,8 @@ namespace TYPO3\CMS\Extbase\Tests\Functional\Persistence\Generic\Mapper;
 use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\Attributes\Test;
 use TYPO3\CMS\Core\DataHandling\TableColumnType;
+use TYPO3\CMS\Core\Schema\FieldTypeFactory;
+use TYPO3\CMS\Core\Schema\RelationMap;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\Relation;
@@ -32,11 +34,13 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
     protected bool $initializeDatabase = false;
 
     protected ColumnMapFactory $columnMapFactory;
+    protected FieldTypeFactory $fieldTypeFactory;
 
     protected function setUp(): void
     {
         parent::setUp();
         $this->columnMapFactory = $this->get(ColumnMapFactory::class);
+        $this->fieldTypeFactory = $this->get(FieldTypeFactory::class);
     }
 
     public static function createWithGroupTypeDataProvider(): \Generator
@@ -97,7 +101,7 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
     {
         self::assertEquals(
             $expectedColumnMap,
-            $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class)
+            $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class)
         );
     }
 
@@ -219,7 +223,7 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
     {
         self::assertEquals(
             $expectedColumnMap,
-            $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class)
+            $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class)
         );
     }
 
@@ -248,7 +252,7 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
     {
         self::assertEquals(
             $expectedColumnMap,
-            $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class)
+            $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class)
         );
     }
 
@@ -284,7 +288,7 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
     {
         self::assertEquals(
             $expectedColumnMap,
-            $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class)
+            $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class)
         );
     }
 
@@ -304,8 +308,7 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
             ],
         ];
 
-        $columnMap = $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class);
-
+        $columnMap = $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class);
         self::assertSame(
             [
                 'fieldname' => 'foo_model',
@@ -330,8 +333,7 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
             ],
         ];
 
-        $columnMap = $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class);
-
+        $columnMap = $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class);
         self::assertSame(
             [
                 'fieldname' => 'foo_model',
@@ -364,7 +366,8 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
             ],
         ];
 
-        self::assertEquals($expectedColumnMap, $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class));
+        $columnMap = $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class);
+        self::assertEquals($expectedColumnMap, $columnMap);
     }
 
     #[Test]
@@ -390,7 +393,8 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
             ],
         ];
 
-        self::assertEquals($expectedColumnMap, $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class));
+        $columnMap = $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class);
+        self::assertEquals($expectedColumnMap, $columnMap);
     }
 
     #[Test]
@@ -416,7 +420,8 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
             ],
         ];
 
-        self::assertEquals($expectedColumnMap, $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class));
+        $columnMap = $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class);
+        self::assertEquals($expectedColumnMap, $columnMap);
     }
 
     public static function columnMapIsInitializedWithFieldEvaluationsForDateTimeFieldsDataProvider(): array
@@ -442,8 +447,7 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
             ],
         ];
 
-        $columnMap = $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class);
-
+        $columnMap = $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class);
         self::assertSame($expectedValue, $columnMap->getDateTimeStorageFormat());
     }
 
@@ -490,8 +494,7 @@ final class ColumnMapFactoryTest extends FunctionalTestCase
             ],
         ];
 
-        $columnMap = $this->columnMapFactory->create($columnName, $columnConfiguration, $propertyName, ColumnMapFactoryEntityFixture::class);
-
+        $columnMap = $this->columnMapFactory->create($this->fieldTypeFactory->createFieldType($columnName, $columnConfiguration, 'virtual', new RelationMap()), $propertyName, ColumnMapFactoryEntityFixture::class);
         self::assertSame($expectedType, $columnMap->getType());
     }
 }
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/DataMapperTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/DataMapperTest.php
index d2c9b0477e78b24db3ba09cf28be69c66fdc5963..a6ea93436daaa8f3a76c4ea7c3f7436499db03b6 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/DataMapperTest.php
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/DataMapperTest.php
@@ -367,17 +367,17 @@ final class DataMapperTest extends FunctionalTestCase
     #[Test]
     public function mapDateTimeHandlesDifferentFieldEvaluations(string|int|null $value, ?string $storageFormat, ?string $expectedValue): void
     {
-        $GLOBALS['TCA']['tx_testdatamapper_domain_model_example']['columns']['initialized_date_time_property']['config']['dbType'] = $storageFormat;
         $rows = [
             [
                 'uid' => 123,
-                'initialized_date_time_property' => $value,
+                'initialized_date_time_property' . ($storageFormat !== null ? '_' . $storageFormat : '') => $value,
             ],
         ];
         $dataMapper = $this->get(DataMapper::class);
         $mappedObjectsArray = $dataMapper->map(Example::class, $rows);
 
-        self::assertSame($expectedValue, $mappedObjectsArray[0]->getInitializedDateTimeProperty()?->format('c'));
+        $getter = 'getInitializedDateTimeProperty' . ($storageFormat !== null ? ucfirst($storageFormat) : '');
+        self::assertSame($expectedValue, $mappedObjectsArray[0]->{$getter}()?->format('c'));
 
         // Flush DataMapFactory cache on each run.
         $cacheManager = $this->get(CacheManager::class);
@@ -404,18 +404,18 @@ final class DataMapperTest extends FunctionalTestCase
         date_default_timezone_set('America/Chicago');
         $usedTimeZone = date_default_timezone_get();
 
-        $GLOBALS['TCA']['tx_testdatamapper_domain_model_example']['columns']['initialized_date_time_property']['config']['dbType'] = $storageFormat;
         $rows = [
             [
                 'uid' => 123,
-                'initialized_date_time_property' => $value,
+                'initialized_date_time_property' . ($storageFormat !== null ? '_' . $storageFormat : '') => $value,
             ],
         ];
         $dataMapper = $this->get(DataMapper::class);
         $mappedObjectsArray = $dataMapper->map(Example::class, $rows);
 
+        $getter = 'getInitializedDateTimeProperty' . ($storageFormat !== null ? ucfirst($storageFormat) : '');
         $expectedValue = $expectedValue !== null ? new \DateTime($expectedValue, new \DateTimeZone($usedTimeZone)) : $expectedValue;
-        self::assertEquals($expectedValue, $mappedObjectsArray[0]->getInitializedDateTimeProperty());
+        self::assertEquals($expectedValue, $mappedObjectsArray[0]->{$getter}());
 
         // Flush DataMapFactory cache on each run.
         $cacheManager = $this->get(CacheManager::class);
diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php
index 58e530646455ee091b61cf52e73e65c87f93356a..eeb59ec5529c541835645d4517607fded8e1be6a 100644
--- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php
+++ b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php
@@ -21,6 +21,8 @@ use Doctrine\Instantiator\InstantiatorInterface;
 use PHPUnit\Framework\Attributes\Test;
 use Psr\EventDispatcher\EventDispatcherInterface;
 use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Schema\Field\SelectRelationFieldType;
+use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
 use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
 use TYPO3\CMS\Extbase\Persistence\ClassesConfiguration;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap;
@@ -58,6 +60,7 @@ final class DataMapperTest extends UnitTestCase
             $this->createMock(CacheManager::class),
             $this->createMock(ClassesConfiguration::class),
             $this->columnMapFactory,
+            $this->createMock(TcaSchemaFactory::class),
             'foo'
         );
 
@@ -78,9 +81,7 @@ final class DataMapperTest extends UnitTestCase
         // Arrange
         $this->columnMapFactory->setOneToManyRelation(
             $this->columnMap,
-            [
-                'foreign_table' => 'tx_myextension_bar',
-            ]
+            new SelectRelationFieldType('foo', ['foreign_table' => 'tx_myextension_bar'], [])
         );
 
         // Act
@@ -96,10 +97,7 @@ final class DataMapperTest extends UnitTestCase
         // Arrange
         $this->columnMapFactory->setOneToManyRelation(
             $this->columnMap,
-            [
-                'foreign_table' => 'tx_myextension_bar',
-                'foreign_default_sortby' => '',
-            ]
+            new SelectRelationFieldType('foo', ['foreign_table' => 'tx_myextension_bar', 'foreign_default_sortby' => ''], [])
         );
 
         // Act
@@ -115,10 +113,7 @@ final class DataMapperTest extends UnitTestCase
         // Arrange
         $this->columnMapFactory->setOneToManyRelation(
             $this->columnMap,
-            [
-                'foreign_table' => 'tx_myextension_bar',
-                'foreign_default_sortby' => 'pid invalid',
-            ]
+            new SelectRelationFieldType('foo', ['foreign_table' => 'tx_myextension_bar', 'foreign_default_sortby' => 'pid invalid'], [])
         );
 
         // Act
@@ -137,10 +132,7 @@ final class DataMapperTest extends UnitTestCase
         // Arrange
         $this->columnMapFactory->setOneToManyRelation(
             $this->columnMap,
-            [
-                'foreign_table' => 'tx_myextension_bar',
-                'foreign_sortby' => 'uid',
-            ]
+            new SelectRelationFieldType('foo', ['foreign_table' => 'tx_myextension_bar', 'foreign_sortby' => 'uid'], [])
         );
 
         // Act
@@ -159,11 +151,7 @@ final class DataMapperTest extends UnitTestCase
         // Arrange
         $this->columnMapFactory->setOneToManyRelation(
             $this->columnMap,
-            [
-                'foreign_table' => 'tx_myextension_bar',
-                'foreign_sortby' => 'uid',
-                'foreign_default_sortby' => 'pid',
-            ]
+            new SelectRelationFieldType('foo', ['foreign_table' => 'tx_myextension_bar', 'foreign_sortby' => 'uid', 'foreign_default_sortby' => 'pid'], [])
         );
 
         // Act
@@ -182,10 +170,7 @@ final class DataMapperTest extends UnitTestCase
         // Arrange
         $this->columnMapFactory->setOneToManyRelation(
             $this->columnMap,
-            [
-                'foreign_table' => 'tx_myextension_bar',
-                'foreign_default_sortby' => 'pid',
-            ]
+            new SelectRelationFieldType('foo', ['foreign_table' => 'tx_myextension_bar', 'foreign_default_sortby' => 'pid'], [])
         );
 
         // Act
@@ -204,10 +189,7 @@ final class DataMapperTest extends UnitTestCase
         // Arrange
         $this->columnMapFactory->setOneToManyRelation(
             $this->columnMap,
-            [
-                'foreign_table' => 'tx_myextension_bar',
-                'foreign_default_sortby' => 'pid desc',
-            ]
+            new SelectRelationFieldType('foo', ['foreign_table' => 'tx_myextension_bar', 'foreign_default_sortby' => 'pid desc'], [])
         );
 
         // Act
@@ -226,10 +208,7 @@ final class DataMapperTest extends UnitTestCase
         // Arrange
         $this->columnMapFactory->setOneToManyRelation(
             $this->columnMap,
-            [
-                'foreign_table' => 'tx_myextension_bar',
-                'foreign_default_sortby' => 'pid desc, title, uid asc',
-            ]
+            new SelectRelationFieldType('foo', ['foreign_table' => 'tx_myextension_bar', 'foreign_default_sortby' => 'pid desc, title, uid asc'], [])
         );
 
         // Act