diff --git a/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
index fdc7289..28d26e1 100644
--- a/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
+++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
@@ -18,6 +18,34 @@ class DefaultTableMapping implements TableMappingInterface {
   protected $entityType;
 
   /**
+   * The base table of the entity.
+   *
+   * @var string
+   */
+  protected $baseTable;
+
+  /**
+   * The table that stores revisions, if the entity supports revisions.
+   *
+   * @var string
+   */
+  protected $revisionTable;
+
+  /**
+   * The table that stores properties, if the entity has multilingual support.
+   *
+   * @var string
+   */
+  protected $dataTable;
+
+  /**
+   * The table that stores revision field data if the entity supports revisions.
+   *
+   * @var string
+   */
+  protected $revisionDataTable;
+
+  /**
    * The field storage definitions of this mapping.
    *
    * @var \Drupal\Core\Field\FieldStorageDefinitionInterface[]
@@ -87,6 +115,160 @@ class DefaultTableMapping implements TableMappingInterface {
   public function __construct(ContentEntityTypeInterface $entity_type, array $storage_definitions) {
     $this->entityType = $entity_type;
     $this->fieldStorageDefinitions = $storage_definitions;
+
+    $this->initializeMapping();
+  }
+
+  /**
+   * Initializes the table mapping.
+   */
+  protected function initializeMapping() {
+    $revisionable = $this->entityType->isRevisionable();
+    $translatable = $this->entityType->isTranslatable();
+
+    // @todo Remove table names from the entity type definition in
+    //   https://www.drupal.org/node/2232465.
+    $this->baseTable = $this->entityType->getBaseTable() ?: $this->entityType->id();
+    if ($revisionable) {
+      $this->revisionTable = $this->entityType->getRevisionTable() ?: $this->entityType->id() . '_revision';
+    }
+    if ($translatable) {
+      $this->dataTable = $this->entityType->getDataTable() ?: $this->entityType->id() . '_field_data';
+    }
+    if ($revisionable && $translatable) {
+      $this->revisionDataTable = $this->entityType->getRevisionDataTable() ?: $this->entityType->id() . '_field_revision';
+    }
+
+    $id_key = $this->entityType->getKey('id');
+    $revision_key = $this->entityType->getKey('revision');
+    $bundle_key = $this->entityType->getKey('bundle');
+    $uuid_key = $this->entityType->getKey('uuid');
+    $langcode_key = $this->entityType->getKey('langcode');
+
+    $shared_table_definitions = array_filter($this->fieldStorageDefinitions, function (FieldStorageDefinitionInterface $definition) {
+      return $this->allowsSharedTableStorage($definition);
+    });
+
+    $key_fields = array_values(array_filter([$id_key, $revision_key, $bundle_key, $uuid_key, $langcode_key]));
+    $all_fields = array_keys($shared_table_definitions);
+    $revisionable_fields = array_keys(array_filter($shared_table_definitions, function (FieldStorageDefinitionInterface $definition) {
+      return $definition->isRevisionable();
+    }));
+    // Make sure the key fields come first in the list of fields.
+    $all_fields = array_merge($key_fields, array_diff($all_fields, $key_fields));
+
+    $revision_metadata_fields = $revisionable ? array_values($this->entityType->getRevisionMetadataKeys()) : [];
+
+    if (!$revisionable && !$translatable) {
+      // The base layout stores all the base field values in the base table.
+      $this->setFieldNames($this->baseTable, $all_fields);
+    }
+    elseif ($revisionable && !$translatable) {
+      // The revisionable layout stores all the base field values in the base
+      // table, except for revision metadata fields. Revisionable fields
+      // denormalized in the base table but also stored in the revision table
+      // together with the entity ID and the revision ID as identifiers.
+      $this->setFieldNames($this->baseTable, array_diff($all_fields, $revision_metadata_fields));
+      $revision_key_fields = [$id_key, $revision_key];
+      $this->setFieldNames($this->revisionTable, array_merge($revision_key_fields, $revisionable_fields));
+    }
+    elseif (!$revisionable && $translatable) {
+      // Multilingual layouts store key field values in the base table. The
+      // other base field values are stored in the data table, no matter
+      // whether they are translatable or not. The data table holds also a
+      // denormalized copy of the bundle field value to allow for more
+      // performant queries. This means that only the UUID is not stored on
+      // the data table.
+      $this
+        ->setFieldNames($this->baseTable, $key_fields)
+        ->setFieldNames($this->dataTable, array_values(array_diff($all_fields, [$uuid_key])));
+    }
+    elseif ($revisionable && $translatable) {
+      // The revisionable multilingual layout stores key field values in the
+      // base table and the revision table holds the entity ID, revision ID and
+      // langcode ID along with revision metadata. The revision data table holds
+      // data field values for all the revisionable fields and the data table
+      // holds the data field values for all non-revisionable fields. The data
+      // field values of revisionable fields are denormalized in the data
+      // table, as well.
+      $this->setFieldNames($this->baseTable, $key_fields);
+
+      // Like in the multilingual, non-revisionable case the UUID is not
+      // in the data table. Additionally, do not store revision metadata
+      // fields in the data table.
+      $data_fields = array_values(array_diff($all_fields, [$uuid_key], $revision_metadata_fields));
+      $this->setFieldNames($this->dataTable, $data_fields);
+
+      $revision_base_fields = array_merge([$id_key, $revision_key, $langcode_key], $revision_metadata_fields);
+      $this->setFieldNames($this->revisionTable, $revision_base_fields);
+
+      $revision_data_key_fields = [$id_key, $revision_key, $langcode_key];
+      $revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields, [$langcode_key]);
+      $this->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields));
+    }
+
+    // Add dedicated tables.
+    $dedicated_table_definitions = array_filter($this->fieldStorageDefinitions, function (FieldStorageDefinitionInterface $definition) {
+      return $this->requiresDedicatedTableStorage($definition);
+    });
+    $extra_columns = [
+      'bundle',
+      'deleted',
+      'entity_id',
+      'revision_id',
+      'langcode',
+      'delta',
+    ];
+    foreach ($dedicated_table_definitions as $field_name => $definition) {
+      $tables = [$this->getDedicatedDataTableName($definition)];
+      if ($revisionable && $definition->isRevisionable()) {
+        $tables[] = $this->getDedicatedRevisionTableName($definition);
+      }
+      foreach ($tables as $table_name) {
+        $this->setFieldNames($table_name, [$field_name]);
+        $this->setExtraColumns($table_name, $extra_columns);
+      }
+    }
+  }
+
+  /**
+   * Gets the base table name.
+   *
+   * @return string
+   *   The table name.
+   */
+  public function getBaseTable() {
+    return $this->baseTable;
+  }
+
+  /**
+   * Gets the revision table name.
+   *
+   * @return string|false
+   *   The table name or FALSE if it is not available.
+   */
+  public function getRevisionTable() {
+    return $this->revisionTable;
+  }
+
+  /**
+   * Gets the data table name.
+   *
+   * @return string|false
+   *   The table name or FALSE if it is not available.
+   */
+  public function getDataTable() {
+    return $this->dataTable;
+  }
+
+  /**
+   * Gets the revision data table name.
+   *
+   * @return string|false
+   *   The table name or FALSE if it is not available.
+   */
+  public function getRevisionDataTable() {
+    return $this->revisionDataTable;
   }
 
   /**
@@ -143,17 +325,13 @@ public function getFieldTableName($field_name) {
       // where field data is stored, otherwise the base table is responsible for
       // storing field data. Revision metadata is an exception as it's stored
       // only in the revision table.
-      // @todo The table mapping itself should know about entity tables. See
-      //   https://www.drupal.org/node/2274017.
-      /** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $storage */
-      $storage = \Drupal::entityManager()->getStorage($this->entityType->id());
       $storage_definition = $this->fieldStorageDefinitions[$field_name];
-      $table_names = [
-        $storage->getDataTable(),
-        $storage->getBaseTable(),
-        $storage->getRevisionTable(),
+      $table_names = array_filter([
+        $this->dataTable,
+        $this->baseTable,
+        $this->revisionTable,
         $this->getDedicatedDataTableName($storage_definition),
-      ];
+      ]);
 
       // Collect field columns.
       $field_columns = [];
@@ -161,7 +339,7 @@ public function getFieldTableName($field_name) {
         $field_columns[] = $this->getFieldColumnName($storage_definition, $property_name);
       }
 
-      foreach (array_filter($table_names) as $table_name) {
+      foreach ($table_names as $table_name) {
         $columns = $this->getAllColumns($table_name);
         // We assume finding one field column belonging to the mapping is enough
         // to identify the field table.
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 22238d4..1e60445 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -308,103 +308,13 @@ public function getTableMapping(array $storage_definitions = NULL) {
     // case, we can statically cache the computed table mapping. If a new set
     // of field storage definitions is passed, for instance when comparing old
     // and new storage schema, we compute the table mapping without caching.
-    // @todo Clean-up this in https://www.drupal.org/node/2274017 so we can
-    //   easily instantiate a new table mapping whenever needed.
     if (!isset($this->tableMapping) || $storage_definitions) {
       $table_mapping_class = $this->temporary ? TemporaryTableMapping::class : DefaultTableMapping::class;
       $definitions = $storage_definitions ?: $this->entityManager->getFieldStorageDefinitions($this->entityTypeId);
+
       /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping|\Drupal\Core\Entity\Sql\TemporaryTableMapping $table_mapping */
       $table_mapping = new $table_mapping_class($this->entityType, $definitions);
 
-      $shared_table_definitions = array_filter($definitions, function (FieldStorageDefinitionInterface $definition) use ($table_mapping) {
-        return $table_mapping->allowsSharedTableStorage($definition);
-      });
-
-      $key_fields = array_values(array_filter([$this->idKey, $this->revisionKey, $this->bundleKey, $this->uuidKey, $this->langcodeKey]));
-      $all_fields = array_keys($shared_table_definitions);
-      $revisionable_fields = array_keys(array_filter($shared_table_definitions, function (FieldStorageDefinitionInterface $definition) {
-        return $definition->isRevisionable();
-      }));
-      // Make sure the key fields come first in the list of fields.
-      $all_fields = array_merge($key_fields, array_diff($all_fields, $key_fields));
-
-      // If the entity is revisionable, gather the fields that need to be put
-      // in the revision table.
-      $revisionable = $this->entityType->isRevisionable();
-      $revision_metadata_fields = $revisionable ? array_values($this->entityType->getRevisionMetadataKeys()) : [];
-
-      $translatable = $this->entityType->isTranslatable();
-      if (!$revisionable && !$translatable) {
-        // The base layout stores all the base field values in the base table.
-        $table_mapping->setFieldNames($this->baseTable, $all_fields);
-      }
-      elseif ($revisionable && !$translatable) {
-        // The revisionable layout stores all the base field values in the base
-        // table, except for revision metadata fields. Revisionable fields
-        // denormalized in the base table but also stored in the revision table
-        // together with the entity ID and the revision ID as identifiers.
-        $table_mapping->setFieldNames($this->baseTable, array_diff($all_fields, $revision_metadata_fields));
-        $revision_key_fields = [$this->idKey, $this->revisionKey];
-        $table_mapping->setFieldNames($this->revisionTable, array_merge($revision_key_fields, $revisionable_fields));
-      }
-      elseif (!$revisionable && $translatable) {
-        // Multilingual layouts store key field values in the base table. The
-        // other base field values are stored in the data table, no matter
-        // whether they are translatable or not. The data table holds also a
-        // denormalized copy of the bundle field value to allow for more
-        // performant queries. This means that only the UUID is not stored on
-        // the data table.
-        $table_mapping
-          ->setFieldNames($this->baseTable, $key_fields)
-          ->setFieldNames($this->dataTable, array_values(array_diff($all_fields, [$this->uuidKey])));
-      }
-      elseif ($revisionable && $translatable) {
-        // The revisionable multilingual layout stores key field values in the
-        // base table, except for language, which is stored in the revision
-        // table along with revision metadata. The revision data table holds
-        // data field values for all the revisionable fields and the data table
-        // holds the data field values for all non-revisionable fields. The data
-        // field values of revisionable fields are denormalized in the data
-        // table, as well.
-        $table_mapping->setFieldNames($this->baseTable, array_values($key_fields));
-
-        // Like in the multilingual, non-revisionable case the UUID is not
-        // in the data table. Additionally, do not store revision metadata
-        // fields in the data table.
-        $data_fields = array_values(array_diff($all_fields, [$this->uuidKey], $revision_metadata_fields));
-        $table_mapping->setFieldNames($this->dataTable, $data_fields);
-
-        $revision_base_fields = array_merge([$this->idKey, $this->revisionKey, $this->langcodeKey], $revision_metadata_fields);
-        $table_mapping->setFieldNames($this->revisionTable, $revision_base_fields);
-
-        $revision_data_key_fields = [$this->idKey, $this->revisionKey, $this->langcodeKey];
-        $revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields, [$this->langcodeKey]);
-        $table_mapping->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields));
-      }
-
-      // Add dedicated tables.
-      $dedicated_table_definitions = array_filter($definitions, function (FieldStorageDefinitionInterface $definition) use ($table_mapping) {
-        return $table_mapping->requiresDedicatedTableStorage($definition);
-      });
-      $extra_columns = [
-        'bundle',
-        'deleted',
-        'entity_id',
-        'revision_id',
-        'langcode',
-        'delta',
-      ];
-      foreach ($dedicated_table_definitions as $field_name => $definition) {
-        $tables = [$table_mapping->getDedicatedDataTableName($definition)];
-        if ($revisionable && $definition->isRevisionable()) {
-          $tables[] = $table_mapping->getDedicatedRevisionTableName($definition);
-        }
-        foreach ($tables as $table_name) {
-          $table_mapping->setFieldNames($table_name, [$field_name]);
-          $table_mapping->setExtraColumns($table_name, $extra_columns);
-        }
-      }
-
       // Cache the computed table mapping only if we are using our internal
       // storage definitions.
       if (!$storage_definitions) {
@@ -685,7 +595,7 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value
    *   A SelectQuery object for loading the entity.
    */
   protected function buildQuery($ids, $revision_id = FALSE) {
-    $query = $this->database->select($this->entityType->getBaseTable(), 'base');
+    $query = $this->database->select($this->baseTable, 'base');
 
     $query->addTag($this->entityTypeId . '_load_multiple');
 
@@ -760,7 +670,7 @@ public function delete(array $entities) {
   protected function doDeleteFieldItems($entities) {
     $ids = array_keys($entities);
 
-    $this->database->delete($this->entityType->getBaseTable())
+    $this->database->delete($this->baseTable)
       ->condition($this->idKey, $ids, 'IN')
       ->execute();
 
@@ -1081,7 +991,7 @@ protected function saveRevision(ContentEntityInterface $entity) {
         $record->{$this->revisionKey} = $insert_id;
       }
       if ($entity->isDefaultRevision()) {
-        $this->database->update($this->entityType->getBaseTable())
+        $this->database->update($this->baseTable)
           ->fields([$this->revisionKey => $record->{$this->revisionKey}])
           ->condition($this->idKey, $record->{$this->idKey})
           ->execute();
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/DefaultTableMappingTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/DefaultTableMappingTest.php
index 39c9a05..0e6b273 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/DefaultTableMappingTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/DefaultTableMappingTest.php
@@ -41,20 +41,20 @@ public function testGetTableNames() {
     // The storage definitions are only used in getColumnNames() so we do not
     // need to provide any here.
     $table_mapping = new DefaultTableMapping($this->entityType, []);
-    $this->assertSame([], $table_mapping->getTableNames());
+    $this->assertSame(['entity_test'], $table_mapping->getTableNames());
 
     $table_mapping->setFieldNames('foo', []);
-    $this->assertSame(['foo'], $table_mapping->getTableNames());
+    $this->assertSame(['entity_test', 'foo'], $table_mapping->getTableNames());
 
     $table_mapping->setFieldNames('bar', []);
-    $this->assertSame(['foo', 'bar'], $table_mapping->getTableNames());
+    $this->assertSame(['entity_test', 'foo', 'bar'], $table_mapping->getTableNames());
 
     $table_mapping->setExtraColumns('baz', []);
-    $this->assertSame(['foo', 'bar', 'baz'], $table_mapping->getTableNames());
+    $this->assertSame(['entity_test', 'foo', 'bar', 'baz'], $table_mapping->getTableNames());
 
     // Test that table names are not duplicated.
     $table_mapping->setExtraColumns('foo', []);
-    $this->assertSame(['foo', 'bar', 'baz'], $table_mapping->getTableNames());
+    $this->assertSame(['entity_test', 'foo', 'bar', 'baz'], $table_mapping->getTableNames());
   }
 
   /**
@@ -362,38 +362,35 @@ public function testGetFieldTableName($table_names, $expected) {
       ->method('getColumns')
       ->willReturn($columns);
 
-    $storage = $this->getMockBuilder('\Drupal\Core\Entity\Sql\SqlContentEntityStorage')
-      ->disableOriginalConstructor()
-      ->getMock();
-
-    $storage
+    $this->entityType
       ->expects($this->any())
       ->method('getBaseTable')
-      ->willReturn(isset($table_names['base']) ? $table_names['base'] : 'base_table');
+      ->willReturn(isset($table_names['base']) ? $table_names['base'] : 'entity_test');
 
-    $storage
+    $this->entityType
       ->expects($this->any())
-      ->method('getDataTable')
-      ->willReturn(isset($table_names['data']) ? $table_names['data'] : NULL);
+      ->method('isTranslatable')
+      ->willReturn(isset($table_names['data']) ? TRUE : FALSE);
 
-    $storage
+    $this->entityType
       ->expects($this->any())
-      ->method('getRevisionTable')
-      ->willReturn(isset($table_names['revision']) ? $table_names['revision'] : NULL);
+      ->method('getDataTable')
+      ->willReturn(isset($table_names['data']) ? $table_names['data'] : FALSE);
 
-    $entity_manager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
-    $entity_manager
+    $this->entityType
       ->expects($this->any())
-      ->method('getStorage')
-      ->willReturn($storage);
+      ->method('isRevisionable')
+      ->willReturn(isset($table_names['revision']) ? TRUE : FALSE);
 
-    $container = $this->getMock('\Symfony\Component\DependencyInjection\ContainerInterface');
-    $container
+    $this->entityType
       ->expects($this->any())
-      ->method('get')
-      ->willReturn($entity_manager);
+      ->method('getRevisionTable')
+      ->willReturn(isset($table_names['revision']) ? $table_names['revision'] : FALSE);
 
-    \Drupal::setContainer($container);
+    $this->entityType
+      ->expects($this->any())
+      ->method('getRevisionMetadataKeys')
+      ->willReturn([]);
 
     $table_mapping = new DefaultTableMapping($this->entityType, [$field_name => $definition]);
 
@@ -431,7 +428,7 @@ public function providerTestGetFieldTableName() {
 
     $data[] = [['data' => 'data_table'], 'data_table'];
     $data[] = [['base' => 'base_table'], 'base_table'];
-    $data[] = [['revision' => 'revision_table'], 'revision_table'];
+    $data[] = [['revision' => 'revision_table'], 'entity_test'];
 
     return $data;
   }
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
index d16ece2..5643b15 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
@@ -389,13 +389,22 @@ public function testGetSchemaBase() {
    * @covers ::processIdentifierSchema
    */
   public function testGetSchemaRevisionable() {
-    $this->entityType = new ContentEntityType([
-      'id' => 'entity_test',
-      'entity_keys' => [
-        'id' => 'id',
-        'revision' => 'revision_id',
-      ],
-    ]);
+    $this->entityType = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityType')
+      ->setConstructorArgs([
+        [
+          'id' => 'entity_test',
+          'entity_keys' => [
+            'id' => 'id',
+            'revision' => 'revision_id',
+          ],
+        ]
+      ])
+      ->setMethods(['getRevisionMetadataKeys'])
+      ->getMock();
+
+    $this->entityType->expects($this->any())
+      ->method('getRevisionMetadataKeys')
+      ->will($this->returnValue([]));
 
     $this->storage->expects($this->exactly(2))
       ->method('getRevisionTable')
@@ -595,14 +604,23 @@ public function testGetSchemaTranslatable() {
    * @covers ::processRevisionDataTable
    */
   public function testGetSchemaRevisionableTranslatable() {
-    $this->entityType = new ContentEntityType([
-      'id' => 'entity_test',
-      'entity_keys' => [
-        'id' => 'id',
-        'revision' => 'revision_id',
-        'langcode' => 'langcode',
-      ],
-    ]);
+    $this->entityType = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityType')
+      ->setConstructorArgs([
+        [
+          'id' => 'entity_test',
+          'entity_keys' => [
+            'id' => 'id',
+            'revision' => 'revision_id',
+            'langcode' => 'langcode',
+          ],
+        ]
+      ])
+      ->setMethods(['getRevisionMetadataKeys'])
+      ->getMock();
+
+    $this->entityType->expects($this->any())
+      ->method('getRevisionMetadataKeys')
+      ->will($this->returnValue([]));
 
     $this->storage->expects($this->exactly(3))
       ->method('getRevisionTable')
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
index bf3fd46..6881dea 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
@@ -205,6 +205,9 @@ public function testGetRevisionTable($revision_table, $expected) {
     $this->entityType->expects($this->once())
       ->method('getRevisionTable')
       ->will($this->returnValue($revision_table));
+    $this->entityType->expects($this->any())
+      ->method('getRevisionMetadataKeys')
+      ->willReturn([]);
 
     $this->setUpEntityStorage();
 
@@ -243,6 +246,9 @@ public function testGetDataTable() {
     $this->entityType->expects($this->exactly(1))
       ->method('getDataTable')
       ->will($this->returnValue('entity_test_field_data'));
+    $this->entityType->expects($this->any())
+      ->method('getRevisionMetadataKeys')
+      ->willReturn([]);
 
     $this->setUpEntityStorage();
 
@@ -276,6 +282,9 @@ public function testGetRevisionDataTable($revision_data_table, $expected) {
     $this->entityType->expects($this->once())
       ->method('getRevisionDataTable')
       ->will($this->returnValue($revision_data_table));
+    $this->entityType->expects($this->any())
+      ->method('getRevisionMetadataKeys')
+      ->willReturn([]);
 
     $this->setUpEntityStorage();
 
