diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
index 96473cfba773f8d5085de5016cb8ee4b54bdd25c..d69b390b7658c2d1a9c20bc28cef6383b41776e7 100644
--- a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
+++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
@@ -29,6 +29,7 @@ use TYPO3\CMS\Core\Domain\Repository\PageRepository;
 use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
+use TYPO3\CMS\Core\Versioning\VersionState;
 use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
 use TYPO3\CMS\Extbase\DomainObject\AbstractValueObject;
 use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
@@ -555,17 +556,15 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
             return $rows;
         }
 
-        /** @var Context $context */
-        $context = $this->objectManager->get(Context::class);
+        $context = GeneralUtility::makeInstance(Context::class);
         if ($workspaceUid === null) {
             $workspaceUid = (int)$context->getPropertyFromAspect('workspace', 'id');
         } else {
             // A custom query is needed, so a custom context is cloned
             $context = clone $context;
-            $context->setAspect('workspace', $this->objectManager->get(WorkspaceAspect::class, $workspaceUid));
+            $context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $workspaceUid));
         }
-        /** @var PageRepository $pageRepository */
-        $pageRepository = $this->objectManager->get(PageRepository::class, $context);
+        $pageRepository = GeneralUtility::makeInstance(PageRepository::class, $context);
 
         // Fetches the move-placeholder in case it is supported
         // by the table and if there's only one row in the result set
@@ -579,10 +578,10 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
             $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
             $queryBuilder->getRestrictions()->removeAll();
             $movePlaceholder = $queryBuilder
-                ->select($tableName . '.*')
+                ->select('*')
                 ->from($tableName)
                 ->where(
-                    $queryBuilder->expr()->eq('t3ver_state', $queryBuilder->createNamedParameter(3, \PDO::PARAM_INT)),
+                    $queryBuilder->expr()->eq('t3ver_state', $queryBuilder->createNamedParameter(VersionState::MOVE_PLACEHOLDER, \PDO::PARAM_INT)),
                     $queryBuilder->expr()->eq('t3ver_wsid', $queryBuilder->createNamedParameter($versionId, \PDO::PARAM_INT)),
                     $queryBuilder->expr()->eq('t3ver_move_id', $queryBuilder->createNamedParameter($rows[0]['uid'], \PDO::PARAM_INT))
                 )
@@ -594,9 +593,25 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
             }
         }
         $overlaidRows = [];
+        $querySettings = $query->getQuerySettings();
         foreach ($rows as $row) {
+            // If current row is a translation select its parent
+            $languageOfCurrentRecord = 0;
+            if ($GLOBALS['TCA'][$tableName]['ctrl']['languageField'] ?? null
+            && $row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']] ?? 0) {
+                $languageOfCurrentRecord = $row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']];
+            }
+            if ($querySettings->getLanguageOverlayMode()
+                && $languageOfCurrentRecord > 0
+                && isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
+                && $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0) {
+                $row = $pageRepository->getRawRecord(
+                    $tableName,
+                    (int)$row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']]
+                );
+            }
+            // Handle workspace overlays
             $pageRepository->versionOL($tableName, $row, true);
-            $querySettings = $query->getQuerySettings();
             if (is_array($row) && $querySettings->getLanguageOverlayMode()) {
                 if ($tableName === 'pages') {
                     $row = $pageRepository->getPageOverlay($row, $querySettings->getLanguageUid());
@@ -604,17 +619,18 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
                     // todo: remove type cast once getLanguageUid strictly returns an int
                     $languageUid = (int)$querySettings->getLanguageUid();
                     if (!$querySettings->getRespectSysLanguage()
-                        && isset($row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']])
-                        && $row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']] > 0
+                        && $languageOfCurrentRecord > 0
                         && (!$query instanceof Query || !$query->getParentQuery())
                     ) {
                         //no parent query means we're processing the aggregate root.
                         //respectSysLanguage is false which means that records returned by the query
                         //might be from different languages (which is desired).
                         //So we need to force language used for overlay to the language of the current record.
-                        $languageUid = $row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']];
+                        $languageUid = $languageOfCurrentRecord;
                     }
-                    if (isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']) && $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0) {
+                    if (isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
+                        && $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0
+                        && $languageOfCurrentRecord > 0) {
                         //force overlay by faking default language record, as getRecordOverlay can only handle default language records
                         $row['uid'] = $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']];
                         $row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']] = 0;
diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
index f57f88767aa45cdb78a93352582a1c75c47b0cab..c419427ab1db0d3a9a0aa618a842e56c198377e7 100644
--- a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
+++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
@@ -16,6 +16,7 @@
 namespace TYPO3\CMS\Extbase\Persistence\Generic\Storage;
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
@@ -715,6 +716,9 @@ class Typo3DbQueryParser
             if (!empty($pageIdStatement)) {
                 $whereClause[] = $pageIdStatement;
             }
+        } elseif (!empty($GLOBALS['TCA'][$tableName]['ctrl']['versioningWS'])) {
+            // Always prevent workspace records from being returned
+            $whereClause[] = $this->queryBuilder->expr()->eq($tableAlias . '.t3ver_oid', 0);
         }
 
         return $whereClause;
@@ -765,7 +769,7 @@ class Typo3DbQueryParser
         if ($ignoreEnableFields && !$includeDeleted) {
             if (!empty($enableFieldsToBeIgnored)) {
                 // array_combine() is necessary because of the way \TYPO3\CMS\Core\Domain\Repository\PageRepository::enableFields() is implemented
-                $statement .= $this->getPageRepository()->enableFields($tableName, -1, array_combine($enableFieldsToBeIgnored, $enableFieldsToBeIgnored));
+                $statement .= $this->getPageRepository()->enableFields($tableName, -1, array_combine($enableFieldsToBeIgnored, $enableFieldsToBeIgnored), true);
             } elseif (!empty($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
                 $statement .= ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
             }
@@ -788,7 +792,9 @@ class Typo3DbQueryParser
     protected function getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted)
     {
         $statement = '';
-        if (!$ignoreEnableFields) {
+        // In case of versioning-preview, enableFields are ignored (checked in Typo3DbBackend::doLanguageAndWorkspaceOverlay)
+        $isUserInWorkspace = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'isOffline');
+        if (!$ignoreEnableFields && !$isUserInWorkspace) {
             $statement .= BackendUtility::BEenableFields($tableName);
         }
         if (!$includeDeleted && !empty($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml
index bdf9e6128336ec7a73df3a3d3dd0bb4a078ae533..a7bf622a742b27845692ce33a6f72d5e7cfd32ff 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml
@@ -54,4 +54,44 @@
 		<deleted>1</deleted>
 		<posts>1</posts>
 	</tx_blogexample_domain_model_blog>
+	<tx_blogexample_domain_model_blog>
+		<uid>6</uid>
+		<pid>0</pid>
+		<title>Blog6Hidden</title>
+		<description>Blog6 Description</description>
+		<logo></logo>
+		<l18n_diffsource></l18n_diffsource>
+		<hidden>1</hidden>
+		<deleted>0</deleted>
+		<posts>1</posts>
+	</tx_blogexample_domain_model_blog>
+
+
+	<tx_blogexample_domain_model_blog>
+		<uid>101</uid>
+		<pid>0</pid>
+		<title>WorkspaceOverlay Blog1</title>
+		<description>WorkspaceOverlay Blog1 Description</description>
+		<logo></logo>
+		<l18n_diffsource></l18n_diffsource>
+		<deleted>0</deleted>
+		<posts>10</posts>
+		<t3ver_oid>1</t3ver_oid>
+		<t3ver_state>-1</t3ver_state>
+		<t3ver_wsid>1</t3ver_wsid>
+	</tx_blogexample_domain_model_blog>
+	<tx_blogexample_domain_model_blog>
+		<uid>102</uid>
+		<pid>0</pid>
+		<title>WorkspaceOverlay Blog6Enabled</title>
+		<description>WorkspaceOverlay Blog6 Description</description>
+		<logo></logo>
+		<l18n_diffsource></l18n_diffsource>
+		<hidden>0</hidden>
+		<deleted>0</deleted>
+		<posts>1</posts>
+		<t3ver_oid>6</t3ver_oid>
+		<t3ver_state>-1</t3ver_state>
+		<t3ver_wsid>1</t3ver_wsid>
+	</tx_blogexample_domain_model_blog>
 </dataset>
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml
index c83e4e7e7e1089222248e2866a100d42c39884f8..4bc8645bf4985c92c6b1d090c3d52ee322d82ec9 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml
@@ -247,4 +247,62 @@
 		<deleted>1</deleted>
 		<hidden>0</hidden>
 	</tx_blogexample_domain_model_post>
+
+
+	<tx_blogexample_domain_model_post>
+		<uid>101</uid>
+		<pid>-1</pid>
+		<tstamp>121319</tstamp>
+		<blog>1</blog>
+		<author>3</author>
+		<reviewer>2</reviewer>
+		<tags>10</tags>
+		<date>1502275450</date>
+		<categories>3</categories>
+		<title>WorkspaceOverlay Post1</title>
+		<content>WorkspaceOverlay Lorem ipsum...</content>
+		<l18n_diffsource></l18n_diffsource>
+		<sorting>1</sorting>
+		<deleted>0</deleted>
+		<related_posts>1</related_posts>
+		<t3ver_oid>1</t3ver_oid>
+		<t3ver_state>-1</t3ver_state>
+		<t3ver_wsid>1</t3ver_wsid>
+	</tx_blogexample_domain_model_post>
+	<tx_blogexample_domain_model_post>
+		<uid>102</uid>
+		<pid>-1</pid>
+		<blog>1</blog>
+		<author>2</author>
+		<reviewer>2</reviewer>
+		<tags>1</tags>
+		<date>1502275450</date>
+		<categories>0</categories>
+		<title>WorkspaceOverlay Post2</title>
+		<content>WorkspaceOverlay Lorem ipsum...</content>
+		<l18n_diffsource></l18n_diffsource>
+		<sorting>2</sorting>
+		<deleted>0</deleted>
+		<t3ver_oid>2</t3ver_oid>
+		<t3ver_state>-1</t3ver_state>
+		<t3ver_wsid>1</t3ver_wsid>
+	</tx_blogexample_domain_model_post>
+	<tx_blogexample_domain_model_post>
+		<uid>103</uid>
+		<pid>-1</pid>
+		<blog>1</blog>
+		<author>2</author>
+		<reviewer>1</reviewer>
+		<tags>1</tags>
+		<date>1502275450</date>
+		<categories>0</categories>
+		<title>WorkspaceOverlay Post3</title>
+		<content>WorkspaceOverlay Lorem ipsum...</content>
+		<l18n_diffsource></l18n_diffsource>
+		<sorting>3</sorting>
+		<deleted>0</deleted>
+		<t3ver_oid>3</t3ver_oid>
+		<t3ver_state>-1</t3ver_state>
+		<t3ver_wsid>1</t3ver_wsid>
+	</tx_blogexample_domain_model_post>
 </dataset>
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/RelationTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/RelationTest.php
index ca68414aed2cc3da999db5fb4b26393729bec0ed..af0e026a9cc6b5b2874a21ab5d269de7b1f45c8e 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/RelationTest.php
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/RelationTest.php
@@ -23,6 +23,7 @@ use ExtbaseTeam\BlogExample\Domain\Repository\PersonRepository;
 use ExtbaseTeam\BlogExample\Domain\Repository\PostRepository;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Domain\Model\Category;
@@ -89,7 +90,7 @@ class RelationTest extends FunctionalTestCase
     public function attachPostToBlogAtTheEnd()
     {
         $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_domain_model_post');
-        $queryBuilder->getRestrictions()->removeAll();
+        $queryBuilder->getRestrictions()->removeAll()->add(new BackendWorkspaceRestriction(0, false));
         $countPostsOriginal = $queryBuilder
             ->count('*')
             ->from('tx_blogexample_domain_model_post')
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/WorkspaceTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/WorkspaceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e70b2bfa7f092dd20bd6cf6b821d6a3e55405378
--- /dev/null
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/WorkspaceTest.php
@@ -0,0 +1,208 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Extbase\Tests\Functional\Persistence;
+
+use ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\UserAspect;
+use TYPO3\CMS\Core\Context\WorkspaceAspect;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Object\ObjectManager;
+use TYPO3\CMS\Extbase\Persistence\QueryInterface;
+use TYPO3\CMS\Extbase\Service\EnvironmentService;
+use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
+
+class WorkspaceTest extends FunctionalTestCase
+{
+    /**
+     * @var array
+     */
+    protected $testExtensionsToLoad = [
+        'typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example',
+    ];
+
+    /**
+     * @var array
+     */
+    protected $coreExtensionsToLoad = [
+        'extbase',
+        'fluid',
+        'workspaces',
+    ];
+
+    /**
+     * @var BlogRepository
+     */
+    protected $blogRepository;
+
+    /**
+     * Sets up this test suite.
+     */
+    protected function setUp(): void
+    {
+        parent::setUp();
+        $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/pages.xml');
+        $this->importDataSet('EXT:extbase/Tests/Functional/Persistence/Fixtures/blogs.xml');
+        $this->importDataSet('EXT:extbase/Tests/Functional/Persistence/Fixtures/posts.xml');
+    }
+
+    protected function tearDown(): void
+    {
+        // Reset to TYPO3_MODE = BE as defined in functional tests
+        GeneralUtility::makeInstance(EnvironmentService::class)->setFrontendMode(false);
+        parent::tearDown(); // TODO: Change the autogenerated stub
+    }
+
+    public function contextDataProvider(): array
+    {
+        return [
+            'test frontend context' => [
+                'context' => 'FE',
+            ],
+            'test backend context' => [
+                'context' => 'BE',
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider contextDataProvider
+     * @param string $context
+     */
+    public function countReturnsCorrectNumberOfBlogs(string $context)
+    {
+        if ($context === 'FE') {
+            $this->setupSubjectInFrontend();
+        } else {
+            $this->setupSubjectInBackend();
+        }
+
+        $query = $this->blogRepository->createQuery();
+
+        $querySettings = $query->getQuerySettings();
+        $querySettings->setRespectStoragePage(false);
+
+        // In workspace all records need to be fetched, thus enableFields is ignored
+        // This means we select even hidden (but not deleted) records for count()
+        self::assertSame(5, $query->execute()->count());
+    }
+
+    /**
+     * @test
+     * @dataProvider contextDataProvider
+     * @param string $context
+     */
+    public function fetchingAllBlogsReturnsCorrectNumberOfBlogs(string $context)
+    {
+        if ($context === 'FE') {
+            $this->setupSubjectInFrontend();
+        } else {
+            $this->setupSubjectInBackend();
+        }
+
+        $query = $this->blogRepository->createQuery();
+
+        $querySettings = $query->getQuerySettings();
+        $querySettings->setRespectStoragePage(false);
+
+        $query->setOrderings(['uid' => QueryInterface::ORDER_ASCENDING]);
+
+        $blogs = $query->execute()->toArray();
+
+        self::assertSame(4, count($blogs));
+
+        // Check first blog was overlaid with workspace preview
+        $firstBlog = array_shift($blogs);
+        self::assertSame(1, $firstBlog->getUid());
+        self::assertSame('WorkspaceOverlay Blog1', $firstBlog->getTitle());
+
+        // Check last blog was enabled in workspace preview
+        $lastBlog = array_pop($blogs);
+        self::assertSame(6, $lastBlog->getUid());
+        self::assertSame('WorkspaceOverlay Blog6Enabled', $lastBlog->getTitle());
+    }
+
+    /**
+     * @test
+     * @dataProvider contextDataProvider
+     * @param string $context
+     */
+    public function fetchingBlogReturnsOverlaidWorkspaceVersionForRelations(string $context)
+    {
+        if ($context === 'FE') {
+            $this->setupSubjectInFrontend();
+        } else {
+            $this->setupSubjectInBackend();
+        }
+
+        $query = $this->blogRepository->createQuery();
+
+        $querySettings = $query->getQuerySettings();
+        $querySettings->setStoragePageIds([0]);
+
+        $query->matching($query->equals('uid', 1));
+
+        $blog = $query->execute()->getFirst();
+        $posts = $blog->getPosts()->toArray();
+
+        self::assertSame('WorkspaceOverlay Blog1', $blog->getTitle());
+        self::assertCount(10, (array)$posts);
+        self::assertSame('WorkspaceOverlay Post1', $posts[0]->getTitle());
+        self::assertSame('WorkspaceOverlay Post2', $posts[1]->getTitle());
+        self::assertSame('WorkspaceOverlay Post3', $posts[2]->getTitle());
+    }
+
+    /**
+     * Minimal frontend environment to satisfy Extbase Typo3DbBackend
+     */
+    protected function setupSubjectInFrontend()
+    {
+        $context = new Context(
+            [
+                'workspace' => new WorkspaceAspect(1),
+            ]
+        );
+        GeneralUtility::setSingletonInstance(Context::class, $context);
+        GeneralUtility::makeInstance(EnvironmentService::class)->setFrontendMode(true);
+
+        $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
+        $this->blogRepository = $objectManager->get(BlogRepository::class);
+    }
+
+    /**
+     * Minimal backend user configuration to satisfy Extbase Typo3DbBackend
+     */
+    protected function setupSubjectInBackend()
+    {
+        $backendUser = new BackendUserAuthentication();
+        $backendUser->workspace = 1;
+        $GLOBALS['BE_USER'] = $backendUser;
+        $context = new Context(
+            [
+                'backend.user' => new UserAspect($backendUser),
+                'workspace' => new WorkspaceAspect(1),
+            ]
+        );
+        GeneralUtility::setSingletonInstance(Context::class, $context);
+
+        $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
+        $this->blogRepository = $objectManager->get(BlogRepository::class);
+    }
+}
diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbBackendTest.php b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbBackendTest.php
index 795aaf3fa8fec30ed6b6d732564d2e9a81c3ed43..17f97e864c840899a1ee8ca8b09b77d6c4e61d18 100644
--- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbBackendTest.php
+++ b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbBackendTest.php
@@ -17,15 +17,21 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Storage;
 
 use Doctrine\DBAL\Driver\Statement;
 use Prophecy\Argument;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\WorkspaceAspect;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
 use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
+use TYPO3\CMS\Core\Domain\Repository\PageRepository;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\DomainObject\AbstractValueObject;
 use TYPO3\CMS\Extbase\Object\ObjectManager;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
+use TYPO3\CMS\Extbase\Persistence\Generic\Query;
 use TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend;
+use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
 use TYPO3\CMS\Extbase\Service\EnvironmentService;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
@@ -40,12 +46,6 @@ class Typo3DbBackendTest extends UnitTestCase
      */
     protected $resetSingletonInstances = true;
 
-    public function setUp(): void
-    {
-        parent::setUp();
-        $GLOBALS['TSFE'] = new \stdClass();
-    }
-
     /**
      * @return array
      */
@@ -134,4 +134,50 @@ class Typo3DbBackendTest extends UnitTestCase
         $result = $mockTypo3DbBackend->getUidOfAlreadyPersistedValueObject($mockValueObject);
         self::assertSame($expectedUid, $result);
     }
+
+    /**
+     * @test
+     */
+    public function overlayLanguageAndWorkspaceChangesUidIfInPreview()
+    {
+        $comparisonRow = [
+            'uid' => '42',
+            'pid' => '42',
+            '_ORIG_pid' => '42',
+            '_ORIG_uid' => '43'
+        ];
+        $row = [
+            'uid' => '42',
+            'pid' => '42'
+        ];
+        $workspaceVersion = [
+            'uid' => '43',
+            'pid' => '42'
+        ];
+        $mockQuerySettings = $this->getMockBuilder(Typo3QuerySettings::class)
+            ->setMethods(['dummy'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $workspaceUid = 2;
+
+        $sourceMock = new \TYPO3\CMS\Extbase\Persistence\Generic\Qom\Selector('tx_foo', 'Tx_Foo');
+        $context = new Context([
+            'workspace' => new WorkspaceAspect($workspaceUid)
+        ]);
+        $pageRepositoryMock = $this->getMockBuilder(PageRepository::class)
+            ->setMethods(['movePlhOL', 'getWorkspaceVersionOfRecord'])
+            ->setConstructorArgs([$context])
+            ->getMock();
+        $query = new Query('random');
+        $query->setQuerySettings($mockQuerySettings);
+        $pageRepositoryMock->expects(self::once())->method('getWorkspaceVersionOfRecord')->with($workspaceUid, 'tx_foo', '42')->willReturn($workspaceVersion);
+        $environmentService = new EnvironmentService();
+        $environmentService->setFrontendMode(true);
+        GeneralUtility::setSingletonInstance(Context::class, $context);
+        GeneralUtility::addInstance(PageRepository::class, $pageRepositoryMock);
+        $mockTypo3DbBackend = $this->getAccessibleMock(Typo3DbBackend::class, ['dummy'], [], '', false);
+        $mockTypo3DbBackend->injectEnvironmentService($environmentService);
+        self::assertSame([$comparisonRow], $mockTypo3DbBackend->_call('overlayLanguageAndWorkspace', $sourceMock, [$row], $query));
+    }
 }
diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php
index 6b9bd0562adf919378ba22587af9ac2ec641497b..087a1ad2f6405d0110be1421b80a3f3f69ea489c 100644
--- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php
+++ b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php
@@ -727,14 +727,10 @@ class Typo3DbQueryParserTest extends UnitTestCase
         $mockQuerySettings->setIgnoreEnableFields(!$respectEnableFields);
         $mockQuerySettings->setIncludeDeleted(!$respectEnableFields);
 
-        /** @var $mockEnvironmentService \TYPO3\CMS\Extbase\Service\EnvironmentService | \PHPUnit\Framework\MockObject\MockObject */
-        $mockEnvironmentService = $this->getMockBuilder(EnvironmentService::class)
-            ->setMethods(['isEnvironmentInFrontendMode'])
-            ->getMock();
-        $mockEnvironmentService->expects(self::any())->method('isEnvironmentInFrontendMode')->willReturn($mode === 'FE');
-
+        $environmentService = new EnvironmentService();
+        $environmentService->setFrontendMode($mode === 'FE');
         $mockTypo3DbQueryParser = $this->getAccessibleMock(Typo3DbQueryParser::class, ['dummy'], [], '', false);
-        $mockTypo3DbQueryParser->_set('environmentService', $mockEnvironmentService);
+        $mockTypo3DbQueryParser->injectEnvironmentService($environmentService);
         $actualSql = $mockTypo3DbQueryParser->_call('getVisibilityConstraintStatement', $mockQuerySettings, $tableName, $tableName);
         self::assertSame($expectedSql, $actualSql);
         unset($GLOBALS['TCA'][$tableName]);
@@ -762,14 +758,11 @@ class Typo3DbQueryParserTest extends UnitTestCase
         $mockQuerySettings->expects(self::once())->method('getEnableFieldsToBeIgnored')->willReturn([]);
         $mockQuerySettings->expects(self::once())->method('getIncludeDeleted')->willReturn(true);
 
-        /** @var $mockEnvironmentService \TYPO3\CMS\Extbase\Service\EnvironmentService | \PHPUnit\Framework\MockObject\MockObject */
-        $mockEnvironmentService = $this->getMockBuilder(EnvironmentService::class)
-            ->setMethods(['isEnvironmentInFrontendMode'])
-            ->getMock();
-        $mockEnvironmentService->expects(self::any())->method('isEnvironmentInFrontendMode')->willReturn(true);
-
+        $environmentService = new EnvironmentService();
+        $environmentService->setFrontendMode(true);
         $mockTypo3DbQueryParser = $this->getAccessibleMock(Typo3DbQueryParser::class, ['dummy'], [], '', false);
-        $mockTypo3DbQueryParser->_set('environmentService', $mockEnvironmentService);
+        $mockTypo3DbQueryParser->injectEnvironmentService($environmentService);
+
         $mockTypo3DbQueryParser->_call('getVisibilityConstraintStatement', $mockQuerySettings, $tableName, $tableName);
         unset($GLOBALS['TCA'][$tableName]);
     }