diff --git a/typo3/sysext/core/Classes/Category/Collection/CategoryCollection.php b/typo3/sysext/core/Classes/Category/Collection/CategoryCollection.php
index b0a54629adea5e20e9347f1b086d3fa7f4f8befa..07b6cefc2b3390497a2ea976b253bf74f0cabdc3 100644
--- a/typo3/sysext/core/Classes/Category/Collection/CategoryCollection.php
+++ b/typo3/sysext/core/Classes/Category/Collection/CategoryCollection.php
@@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\Category\Collection;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Collection\AbstractRecordCollection;
 use TYPO3\CMS\Core\Collection\CollectionInterface;
 use TYPO3\CMS\Core\Collection\EditableCollectionInterface;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Database\Query\QueryBuilder;
+use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -96,53 +98,93 @@ class CategoryCollection extends AbstractRecordCollection implements EditableCol
      */
     public static function load($id, $fillItems = false, $tableName = '', $fieldName = '')
     {
-        $collectionRecord = self::getDatabaseConnection()->exec_SELECTgetSingleRow(
-            '*',
-            static::$storageTableName,
-            'uid = ' . (int)$id . BackendUtility::deleteClause(static::$storageTableName)
-        );
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getQueryBuilderForTable(static::$storageTableName);
+
+        $queryBuilder->getRestrictions()
+            ->removeAll()
+            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+
+        $collectionRecord = $queryBuilder->select('*')
+            ->from(static::$storageTableName)
+            ->where(
+                $queryBuilder->expr()->eq('uid', (int)$id)
+            )
+            ->setMaxResults(1)
+            ->execute()
+            ->fetch();
+
         $collectionRecord['table_name'] = $tableName;
         $collectionRecord['field_name'] = $fieldName;
+
         return self::create($collectionRecord, $fillItems);
     }
 
     /**
-     * Gets the collected records in this collection, by
+     * Selects the collected records in this collection, by
      * looking up the MM relations of this record to the
      * table name defined in the local field 'table_name'.
      *
+     * @return QueryBuilder
+     */
+    protected function getCollectedRecordsQueryBuilder()
+    {
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getQueryBuilderForTable(static::$storageTableName);
+        $queryBuilder->getRestrictions()->removeAll();
+
+        $queryBuilder->select($this->getItemTableName() . '.*')
+            ->from(static::$storageTableName)
+            ->join(
+                static::$storageTableName,
+                'sys_category_record_mm',
+                'sys_category_record_mm',
+                $queryBuilder->expr()->eq(
+                    'sys_category_record_mm.uid_local',
+                    $queryBuilder->quoteIdentifier(static::$storageTableName . '.uid')
+                )
+            )
+            ->join(
+                'sys_category_record_mm',
+                $this->getItemTableName(),
+                $this->getItemTableName(),
+                $queryBuilder->expr()->eq(
+                    'sys_category_record_mm.uid_foreign',
+                    $queryBuilder->quoteIdentifier($this->getItemTableName() . '.uid')
+                )
+            )
+            ->where(
+                $queryBuilder->expr()->eq(static::$storageTableName . '.uid', (int)$this->getIdentifier()),
+                $queryBuilder->expr()->eq(
+                    'sys_category_record_mm.tablenames',
+                    $queryBuilder->createNamedParameter($this->getItemTableName())
+                ),
+                $queryBuilder->expr()->eq(
+                    'sys_category_record_mm.fieldname',
+                    $queryBuilder->createNamedParameter($this->getRelationFieldName())
+                )
+            );
+
+        return $queryBuilder;
+    }
+
+    /**
+     * Gets the collected records in this collection, by
+     * using <getCollectedRecordsQueryBuilder>.
+     *
      * @return array
      */
     protected function getCollectedRecords()
     {
-        $db = self::getDatabaseConnection();
+        $relatedRecords = [];
 
-        $relatedRecords = array();
-        // Assemble where clause
-        $where = 'AND ' . self::$storageTableName . '.uid = ' . (int)$this->getIdentifier();
-        // Add condition on tablenames fields
-        $where .= ' AND sys_category_record_mm.tablenames = ' . $db->fullQuoteStr(
-            $this->getItemTableName(),
-            'sys_category_record_mm'
-        );
-        // Add condition on fieldname field
-        $where .= ' AND sys_category_record_mm.fieldname = ' . $db->fullQuoteStr(
-            $this->getRelationFieldName(),
-            'sys_category_record_mm'
-        );
-        $resource = $db->exec_SELECT_mm_query(
-            $this->getItemTableName() . '.*',
-            self::$storageTableName,
-            'sys_category_record_mm',
-            $this->getItemTableName(),
-            $where
-        );
-        if ($resource) {
-            while ($record = $db->sql_fetch_assoc($resource)) {
-                $relatedRecords[] = $record;
-            }
-            $db->sql_free_result($resource);
+        $queryBuilder = $this->getCollectedRecordsQueryBuilder();
+        $result = $queryBuilder->execute();
+
+        while ($record = $result->fetch()) {
+            $relatedRecords[] = $record;
         }
+
         return $relatedRecords;
     }
 
diff --git a/typo3/sysext/frontend/Classes/Category/Collection/CategoryCollection.php b/typo3/sysext/frontend/Classes/Category/Collection/CategoryCollection.php
index 64efce3642713e71bdbb87546dea8600e8e55ede..f01c19fba46d3d1502f37238ccfcdb0292e78a2a 100644
--- a/typo3/sysext/frontend/Classes/Category/Collection/CategoryCollection.php
+++ b/typo3/sysext/frontend/Classes/Category/Collection/CategoryCollection.php
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Frontend\Category\Collection;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -35,7 +37,8 @@ class CategoryCollection extends \TYPO3\CMS\Core\Category\Collection\CategoryCol
     public static function create(array $collectionRecord, $fillItems = false)
     {
         /** @var $collection \TYPO3\CMS\Frontend\Category\Collection\CategoryCollection */
-        $collection = GeneralUtility::makeInstance(__CLASS__,
+        $collection = GeneralUtility::makeInstance(
+            __CLASS__,
             $collectionRecord['table_name'],
             $collectionRecord['field_name']
         );
@@ -62,13 +65,23 @@ class CategoryCollection extends \TYPO3\CMS\Core\Category\Collection\CategoryCol
      */
     public static function load($id, $fillItems = false, $tableName = '', $fieldName = '')
     {
-        $collectionRecord = self::getDatabaseConnection()->exec_SELECTgetSingleRow(
-            '*',
-            static::$storageTableName,
-            'uid = ' . (int)$id . self::getTypoScriptFrontendController()->sys_page->enableFields(static::$storageTableName)
-        );
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getQueryBuilderForTable(static::$storageTableName);
+        $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
+
+        $collectionRecord = $queryBuilder
+            ->select('*')
+            ->from(static::$storageTableName)
+            ->where(
+                $queryBuilder->expr()->eq('uid', (int)$id)
+            )
+            ->setMaxResults(1)
+            ->execute()
+            ->fetch();
+
         $collectionRecord['table_name'] = $tableName;
         $collectionRecord['field_name'] = $fieldName;
+
         return self::create($collectionRecord, $fillItems);
     }
 
@@ -84,75 +97,73 @@ class CategoryCollection extends \TYPO3\CMS\Core\Category\Collection\CategoryCol
      */
     protected function getCollectedRecords()
     {
-        $db = self::getDatabaseConnection();
-
-        $relatedRecords = array();
-        // Assemble where clause
-        $where = 'AND ' . self::$storageTableName . '.uid = ' . (int)$this->getIdentifier();
-        // Add condition on tablenames fields
-        $where .= ' AND sys_category_record_mm.tablenames = ' . $db->fullQuoteStr(
-            $this->getItemTableName(),
-            'sys_category_record_mm'
-        );
-        // Add condition on fieldname field
-        $where .= ' AND sys_category_record_mm.fieldname = ' . $db->fullQuoteStr(
-            $this->getRelationFieldName(),
-            'sys_category_record_mm'
-        );
-        // Add enable fields for item table
+        $relatedRecords = [];
+
+        $queryBuilder = $this->getCollectedRecordsQueryBuilder();
+        $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
         $tsfe = self::getTypoScriptFrontendController();
-        $where .= $tsfe->sys_page->enableFields($this->getItemTableName());
+
         // If language handling is defined for item table, add language condition
         if (isset($GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['languageField'])) {
             // Consider default or "all" language
-            $languageField = $this->getItemTableName() . '.' . $GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['languageField'];
-            $languageCondition = $languageField . ' IN (0, -1)';
+            $languageField = sprintf(
+                '%s.%s',
+                $this->getItemTableName(),
+                $GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['languageField']
+            );
+
+            $languageConstraint = $queryBuilder->expr()->in($languageField, [0, -1]);
+
             // If not in default language, also consider items in current language with no original
             if ($tsfe->sys_language_content > 0) {
-                $languageCondition .= '
-					OR (' . $languageField . ' = ' . (int)$tsfe->sys_language_content . '
-					AND ' . $this->getItemTableName() . '.' .
-                    $GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['transOrigPointerField'] . ' = 0)
-				';
+                $transOrigPointerField = sprintf(
+                    '%s.%s',
+                    $this->getItemTableName(),
+                    $GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['transOrigPointerField']
+                );
+
+                $languageConstraint = $queryBuilder->expr()->orX(
+                    $languageConstraint,
+                    $queryBuilder->expr()->andX(
+                        $queryBuilder->expr()->eq($languageField, (int)$tsfe->sys_language_content),
+                        $queryBuilder->expr()->eq($transOrigPointerField, 0)
+                    )
+                );
             }
-            $where .= ' AND (' . $languageCondition . ')';
+
+            $queryBuilder->andWhere($languageConstraint);
         }
+
         // Get the related records from the database
-        $resource = $db->exec_SELECT_mm_query(
-            $this->getItemTableName() . '.*',
-            self::$storageTableName,
-            'sys_category_record_mm',
-            $this->getItemTableName(),
-            $where
-        );
+        $result = $queryBuilder->execute();
 
-        if ($resource) {
-            while ($record = $db->sql_fetch_assoc($resource)) {
-                // Overlay the record for workspaces
-                $tsfe->sys_page->versionOL(
-                    $this->getItemTableName(),
-                    $record
-                );
-                // Overlay the record for translations
-                if (is_array($record) && $tsfe->sys_language_contentOL) {
-                    if ($this->getItemTableName() === 'pages') {
-                        $record = $tsfe->sys_page->getPageOverlay($record);
-                    } else {
-                        $record = $tsfe->sys_page->getRecordOverlay(
-                            $this->getItemTableName(),
-                            $record,
-                            $tsfe->sys_language_content,
-                            $tsfe->sys_language_contentOL
-                        );
-                    }
-                }
-                // Record may have been unset during the overlay process
-                if (is_array($record)) {
-                    $relatedRecords[] = $record;
+        while ($record = $result->fetch()) {
+            // Overlay the record for workspaces
+            $tsfe->sys_page->versionOL(
+                $this->getItemTableName(),
+                $record
+            );
+
+            // Overlay the record for translations
+            if (is_array($record) && $tsfe->sys_language_contentOL) {
+                if ($this->getItemTableName() === 'pages') {
+                    $record = $tsfe->sys_page->getPageOverlay($record);
+                } else {
+                    $record = $tsfe->sys_page->getRecordOverlay(
+                        $this->getItemTableName(),
+                        $record,
+                        $tsfe->sys_language_content,
+                        $tsfe->sys_language_contentOL
+                    );
                 }
             }
-            $db->sql_free_result($resource);
+
+            // Record may have been unset during the overlay process
+            if (is_array($record)) {
+                $relatedRecords[] = $record;
+            }
         }
+
         return $relatedRecords;
     }