diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
index dfa8198..76d4ab8 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
@@ -141,11 +141,11 @@ public function loadMultiple(array $ids = NULL) {
       $queried_entities = $this->buildQuery($ids);
     }
 
-    // Pass all entities loaded from the database through $this->attachLoad(),
+    // Pass all entities loaded from the database through $this->postLoad(),
     // which calls the
     // entity type specific load callback, for example hook_node_type_load().
     if (!empty($queried_entities)) {
-      $this->attachLoad($queried_entities);
+      $this->postLoad($queried_entities);
       $entities += $queried_entities;
     }
 
@@ -286,38 +286,6 @@ protected function buildQuery($ids, $revision_id = FALSE) {
   }
 
   /**
-   * Attaches data to entities upon loading.
-   *
-   * This will attach fields, if the entity is fieldable. It calls
-   * hook_entity_load() for modules which need to add data to all entities.
-   * It also calls hook_TYPE_load() on the loaded entities. For example
-   * hook_node_load() or hook_user_load(). If your hook_TYPE_load()
-   * expects special parameters apart from the queried entities, you can set
-   * $this->hookLoadArguments prior to calling the method.
-   * See Drupal\node\NodeStorageController::attachLoad() for an example.
-   *
-   * @param $queried_entities
-   *   Associative array of query results, keyed on the entity ID.
-   * @param $revision_id
-   *   ID of the revision that was loaded, or FALSE if the most current revision
-   *   was loaded.
-   */
-  protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
-    // Call hook_entity_load().
-    foreach (\Drupal::moduleHandler()->getImplementations('entity_load') as $module) {
-      $function = $module . '_entity_load';
-      $function($queried_entities, $this->entityType);
-    }
-    // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are
-    // always the queried entities, followed by additional arguments set in
-    // $this->hookLoadArguments.
-    $args = array_merge(array($queried_entities), $this->hookLoadArguments);
-    foreach (\Drupal::moduleHandler()->getImplementations($this->entityType . '_load') as $module) {
-      call_user_func_array($module . '_' . $this->entityType . '_load', $args);
-    }
-  }
-
-  /**
    * Implements Drupal\Core\Entity\EntityStorageControllerInterface::create().
    */
   public function create(array $values) {
diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
index b30d9ec..f258353 100644
--- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
@@ -142,11 +142,11 @@ public function loadMultiple(array $ids = NULL) {
       $queried_entities = $query_result->fetchAllAssoc($this->idKey);
     }
 
-    // Pass all entities loaded from the database through $this->attachLoad(),
+    // Pass all entities loaded from the database through $this->postLoad(),
     // which attaches fields (if supported by the entity type) and calls the
     // entity type specific load callback, for example hook_node_load().
     if (!empty($queried_entities)) {
-      $this->attachLoad($queried_entities);
+      $this->postLoad($queried_entities);
       $entities += $queried_entities;
     }
 
@@ -245,22 +245,6 @@ protected function buildQuery($ids, $revision_id = FALSE) {
   }
 
   /**
-   * Attaches data to entities upon loading.
-   *
-   * @param $queried_entities
-   *   Associative array of query results, keyed on the entity ID.
-   * @param $load_revision
-   *   (optional) TRUE if the revision should be loaded, defaults to FALSE.
-   */
-  protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
-    // Call hook_entity_load().
-    foreach (\Drupal::moduleHandler()->getImplementations('entity_load') as $module) {
-      $function = $module . '_entity_load';
-      $function($queried_entities, $this->entityType);
-    }
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function create(array $values) {
diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index e842208..e11ccbf 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -342,6 +342,17 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont
    * {@inheritdoc}
    */
   public static function postLoad(EntityStorageControllerInterface $storage_controller, array $entities) {
+    $entity_type = $storage_controller->entityType();
+    // Call hook_entity_load().
+    foreach (\Drupal::moduleHandler()->getImplementations('entity_load') as $module) {
+      $function = $module . '_entity_load';
+      $function($entities, $entity_type);
+    }
+    // Call hook_TYPE_load().
+    foreach (\Drupal::moduleHandler()->getImplementations($entity_type . '_load') as $module) {
+      $function = $module . '_' . $entity_type . '_load';
+      $function($entities);
+    }
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php
index f02bb1e..68d0a64 100644
--- a/core/lib/Drupal/Core/Entity/EntityInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityInterface.php
@@ -207,7 +207,7 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr
   public static function postDelete(EntityStorageControllerInterface $storage_controller, array $entities);
 
   /**
-   * Acts on loaded entities before the load hook is invoked.
+   * Calls the entity load hooks.
    *
    * @param EntityStorageControllerInterface $storage_controller
    *   The entity storage controller object.
diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
index f303f79..e721847 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
@@ -45,15 +45,6 @@
   protected $entityInfo;
 
   /**
-   * Additional arguments to pass to hook_TYPE_load().
-   *
-   * Set before calling Drupal\Core\Entity\DatabaseStorageController::attachLoad().
-   *
-   * @var array
-   */
-  protected $hookLoadArguments = array();
-
-  /**
    * Name of the entity's ID field in the entity database table.
    *
    * @var string
@@ -87,6 +78,20 @@ public function __construct($entity_type, $entity_info) {
   /**
    * {@inheritdoc}
    */
+  public function entityType() {
+    return $this->entityType;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function entityInfo() {
+    return $this->entityInfo;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function loadUnchanged($id) {
     $this->resetCache(array($id));
     return $this->load($id);
@@ -152,4 +157,15 @@ protected function invokeHook($hook, EntityInterface $entity) {
     module_invoke_all('entity_' . $hook, $entity, $this->entityType);
   }
 
+  /**
+   * Attaches data to entities upon loading.
+   *
+   * @param $queried_entities
+   *   Associative array of query results, keyed on the entity ID.
+   */
+  protected function postLoad(array &$queried_entities) {
+    $entity_class = $this->entityInfo['class'];
+    $entity_class::postLoad($this, $queried_entities);
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php
index 791eb44..f09c528 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php
@@ -153,4 +153,18 @@ public function save(EntityInterface $entity);
    */
   public function getQueryServicename();
 
+  /**
+   * Returns the current entity type.
+   *
+   * @return string
+   */
+  public function entityType();
+
+  /**
+   * Returns the current entity info.
+   *
+   * @return string
+   */
+  public function entityInfo();
+
 }
diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
index 5497efb..e0c457d 100644
--- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
@@ -229,11 +229,11 @@ public function loadMultiple(array $ids = NULL) {
       $queried_entities = $query_result->fetchAllAssoc($this->idKey);
     }
 
-    // Pass all entities loaded from the database through $this->attachLoad(),
+    // Pass all entities loaded from the database through $this->postLoad(),
     // which attaches fields (if supported by the entity type) and calls the
     // entity type specific load callback, for example hook_node_load().
     if (!empty($queried_entities)) {
-      $this->attachLoad($queried_entities);
+      $this->postLoad($queried_entities);
       $entities += $queried_entities;
     }
 
@@ -372,11 +372,11 @@ public function loadRevision($revision_id) {
     $query_result = $this->buildQuery(array(), $revision_id)->execute();
     $queried_entities = $query_result->fetchAllAssoc($this->idKey);
 
-    // Pass the loaded entities from the database through $this->attachLoad(),
+    // Pass the loaded entities from the database through $this->postLoad(),
     // which attaches fields (if supported by the entity type) and calls the
     // entity type specific load callback, for example hook_node_load().
     if (!empty($queried_entities)) {
-      $this->attachLoad($queried_entities, $revision_id);
+      $this->postLoad($queried_entities, $revision_id);
     }
     return reset($queried_entities);
   }
@@ -519,30 +519,17 @@ protected function buildQuery($ids, $revision_id = FALSE) {
    *
    * @param $queried_entities
    *   Associative array of query results, keyed on the entity ID.
-   * @param $load_revision
-   *   (optional) TRUE if the revision should be loaded, defaults to FALSE.
    */
-  protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
+  protected function postLoad(array &$queried_entities) {
     // Map the loaded records into entity objects and according fields.
-    $queried_entities = $this->mapFromStorageRecords($queried_entities, $load_revision);
+    $queried_entities = $this->mapFromStorageRecords($queried_entities, $revision_id);
 
     // Attach field values.
     if ($this->entityInfo['fieldable']) {
-      $this->loadFieldItems($queried_entities, $load_revision ? static::FIELD_LOAD_REVISION : static::FIELD_LOAD_CURRENT);
+      $this->loadFieldItems($queried_entities);
     }
 
-    // Call hook_entity_load().
-    foreach (\Drupal::moduleHandler()->getImplementations('entity_load') as $module) {
-      $function = $module . '_entity_load';
-      $function($queried_entities, $this->entityType);
-    }
-    // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are
-    // always the queried entities, followed by additional arguments set in
-    // $this->hookLoadArguments.
-    $args = array_merge(array($queried_entities), $this->hookLoadArguments);
-    foreach (\Drupal::moduleHandler()->getImplementations($this->entityType . '_load') as $module) {
-      call_user_func_array($module . '_' . $this->entityType . '_load', $args);
-    }
+    parent::postLoad($queried_entities);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php
index 5cf7973..76c7fef 100644
--- a/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php
+++ b/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php
@@ -27,17 +27,20 @@
    *
    * @param array $entities
    *   An array of entities keyed by entity ID.
-   * @param int $age
-   *   EntityStorageControllerInterface::FIELD_LOAD_CURRENT to load the most
-   *   recent revision for all fields, or
-   *   EntityStorageControllerInterface::FIELD_LOAD_REVISION to load the version
-   *   indicated by each entity.
    */
-  protected function loadFieldItems(array $entities, $age) {
+  protected function loadFieldItems(array $entities) {
     if (empty($entities)) {
       return;
     }
 
+    $age = static::FIELD_LOAD_CURRENT;
+    foreach ($entities as $entity) {
+      if (!$entity->isDefaultRevision()) {
+        $age = static::FIELD_LOAD_REVISION;
+        break;
+      }
+    }
+
     // Only the most current revision of non-deleted fields for cacheable entity
     // types can be cached.
     $load_current = $age == static::FIELD_LOAD_CURRENT;
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
index ca99fa6..6b225eb 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
@@ -198,6 +198,14 @@ public static function preCreate(EntityStorageControllerInterface $storage_contr
   /**
    * {@inheritdoc}
    */
+  public static function postLoad(EntityStorageControllerInterface $storage_controller, array $entities) {
+    $storage_controller->loadCategories($entities);
+    parent::postLoad($storage_controller, $entities);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public static function preDelete(EntityStorageControllerInterface $storage_controller, array $entities) {
     $storage_controller->deleteCategories($entities);
     foreach ($entities as $entity) {
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php
index 3007200..f35439e 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php
@@ -50,6 +50,14 @@ public function label($langcode = NULL) {
   /**
    * {@inheritdoc}
    */
+  public static function postLoad(EntityStorageControllerInterface $storage_controller, array $entities) {
+    $storage_controller->loadCategories($entities);
+    parent::postload($storage_controller, $entities);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function postCreate(EntityStorageControllerInterface $storage_controller) {
     parent::postCreate($storage_controller);
 
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/FeedStorageController.php b/core/modules/aggregator/lib/Drupal/aggregator/FeedStorageController.php
index 8f8fd71..56f2dd6 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/FeedStorageController.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/FeedStorageController.php
@@ -19,14 +19,6 @@
 class FeedStorageController extends FieldableDatabaseStorageController implements FeedStorageControllerInterface {
 
   /**
-   * Overrides Drupal\Core\Entity\DataBaseStorageController::attachLoad().
-   */
-  protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
-    parent::attachLoad($queried_entities, $load_revision);
-    $this->loadCategories($queried_entities);
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function loadCategories(array $feeds) {
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/ItemStorageController.php b/core/modules/aggregator/lib/Drupal/aggregator/ItemStorageController.php
index b4aeadd..c19a36e 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/ItemStorageController.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/ItemStorageController.php
@@ -21,14 +21,6 @@
 class ItemStorageController extends FieldableDatabaseStorageController implements ItemStorageControllerInterface {
 
   /**
-   * Overrides Drupal\Core\Entity\DataBaseStorageController::attachLoad().
-   */
-  protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
-    parent::attachLoad($queried_entities, $load_revision);
-    $this->loadCategories($queried_entities);
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function loadCategories(array $entities) {
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php
deleted file mode 100644
index 2078f58..0000000
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\custom_block\CustomBlockStorageController.
- */
-
-namespace Drupal\custom_block;
-
-use Drupal\Core\Entity\FieldableDatabaseStorageController;
-use Drupal\Core\Entity\EntityStorageControllerInterface;
-
-/**
- * Controller class for custom blocks.
- *
- * This extends the Drupal\Core\Entity\DatabaseStorageController class,
- * adding required special handling for custom block entities.
- */
-class CustomBlockStorageController extends FieldableDatabaseStorageController {
-
-  /**
-   * Overrides \Drupal\Core\Entity\DatabaseStorageController::attachLoad().
-   */
-  protected function attachLoad(&$blocks, $load_revision = FALSE) {
-    // Create an array of block types for passing as a load argument.
-    // Note that blocks at this point are still \StdClass objects returned from
-    // the database.
-    foreach ($blocks as $id => $entity) {
-      $types[$entity->type] = $entity->type;
-    }
-
-    // Besides the list of blocks, pass one additional argument to
-    // hook_custom_block_load(), containing a list of block types that were
-    // loaded.
-    $this->hookLoadArguments = array($types);
-    parent::attachLoad($blocks, $load_revision);
-  }
-
-}
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php
index 426b479..19f8d2a 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php
@@ -21,7 +21,7 @@
  *   label = @Translation("Custom Block"),
  *   bundle_label = @Translation("Custom Block type"),
  *   controllers = {
- *     "storage" = "Drupal\custom_block\CustomBlockStorageController",
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController",
  *     "access" = "Drupal\custom_block\CustomBlockAccessController",
  *     "list" = "Drupal\custom_block\CustomBlockListController",
  *     "view_builder" = "Drupal\custom_block\CustomBlockViewBuilder",
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockLoadHooksTest.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockLoadHooksTest.php
deleted file mode 100644
index 0d20636..0000000
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockLoadHooksTest.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\custom_block\Tests\CustomBlockLoadHooksTest.
- */
-
-namespace Drupal\custom_block\Tests;
-
-/**
- * Tests for the hooks invoked during custom_block_load().
- */
-class CustomBlockLoadHooksTest extends CustomBlockTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('custom_block_test');
-
-  /**
-   * Declares test information.
-   */
-  public static function getInfo() {
-    return array(
-      'name' => 'Custom Block load hooks',
-      'description' => 'Test the hooks invoked when a custom block is being loaded.',
-      'group' => 'Custom Block',
-    );
-  }
-
-  /**
-   * Tests that hook_custom_block_load() is invoked correctly.
-   */
-  public function testHookCustomBlockLoad() {
-    $other_bundle = $this->createCustomBlockType('other');
-    // Create some sample articles and pages.
-    $custom_block1 = $this->createCustomBlock();
-    $custom_block2 = $this->createCustomBlock();
-    $custom_block3 = $this->createCustomBlock();
-    $custom_block4 = $this->createCustomBlock(FALSE, $other_bundle->id());
-
-    // Check that when a set of custom blocks that only contains basic blocks is
-    // loaded, the properties added to the custom block by
-    // custom_block_test_load_custom_block() correctly reflect the expected
-    // values.
-    $custom_blocks = entity_load_multiple_by_properties('custom_block', array('type' => 'basic'));
-    $loaded_custom_block = end($custom_blocks);
-    $this->assertEqual($loaded_custom_block->custom_block_test_loaded_ids, array(
-      $custom_block1->id->value,
-      $custom_block2->id->value,
-      $custom_block3->id->value
-    ), 'hook_custom_block_load() received the correct list of custom_block IDs the first time it was called.');
-    $this->assertEqual($loaded_custom_block->custom_block_test_loaded_types, array('basic'), 'hook_custom_block_load() received the correct list of custom block types the first time it was called.');
-
-    // Now, as part of the same page request, load a set of custom_blocks that contain
-    // both basic and other bundle, and make sure the parameters passed to
-    // custom_block_test_custom_block_load() are correctly updated.
-    $custom_blocks = entity_load_multiple('custom_block', \Drupal::entityQuery('custom_block')->execute(), TRUE);
-    $loaded_custom_block = end($custom_blocks);
-    $this->assertEqual($loaded_custom_block->custom_block_test_loaded_ids, array(
-      $custom_block1->id->value,
-      $custom_block2->id->value,
-      $custom_block3->id->value,
-      $custom_block4->id->value
-    ), 'hook_custom_block_load() received the correct list of custom_block IDs the second time it was called.');
-    $this->assertEqual($loaded_custom_block->custom_block_test_loaded_types, array('basic', 'other'), 'hook_custom_block_load() received the correct list of custom_block types the second time it was called.');
-  }
-}
diff --git a/core/modules/block/custom_block/tests/modules/custom_block_test/custom_block_test.module b/core/modules/block/custom_block/tests/modules/custom_block_test/custom_block_test.module
index b9e848c..812cdbe 100644
--- a/core/modules/block/custom_block/tests/modules/custom_block_test/custom_block_test.module
+++ b/core/modules/block/custom_block/tests/modules/custom_block_test/custom_block_test.module
@@ -11,22 +11,6 @@
 use Drupal\custom_block\Entity\CustomBlock;
 
 /**
- * Implements hook_custom_block_load().
- */
-function custom_block_test_custom_block_load($custom_blocks, $types) {
-  // Add properties to each loaded custom_block which record the parameters that
-  // were passed in to this function, so the tests can check that (a) this hook
-  // was called, and (b) the parameters were what we expected them to be.
-  $ids = array_keys($custom_blocks);
-  ksort($ids);
-  sort($types);
-  foreach ($custom_blocks as $custom_block) {
-    $custom_block->custom_block_test_loaded_ids = $ids;
-    $custom_block->custom_block_test_loaded_types = $types;
-  }
-}
-
-/**
  * Implements hook_custom_block_view().
  */
 function custom_block_test_custom_block_view(CustomBlock $custom_block, $view_mode) {
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index cd7d714..d4e7207 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -467,7 +467,7 @@ function book_children($book_link) {
 /**
  * Implements hook_node_load().
  */
-function book_node_load($nodes, $types) {
+function book_node_load($nodes) {
   $result = db_query("SELECT * FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid IN (:nids)", array(':nids' =>  array_keys($nodes)), array('fetch' => PDO::FETCH_ASSOC));
   foreach ($result as $record) {
     $nodes[$record['nid']]->book = $record;
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
index 751549f..0d93c65 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
@@ -39,12 +39,12 @@ protected function buildQuery($ids, $revision_id = FALSE) {
   /**
    * {@inheritdoc}
    */
-  protected function attachLoad(&$records, $load_revision = FALSE) {
+  protected function postLoad(array &$queried_entities) {
     // Prepare standard comment fields.
-    foreach ($records as &$record) {
+    foreach ($queried_entities as &$record) {
       $record->name = $record->uid ? $record->registered_name : $record->name;
     }
-    parent::attachLoad($records, $load_revision);
+    parent::postLoad($queried_entities);
   }
 
   /**
diff --git a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php
index 1a10efe..5e79959 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php
@@ -576,6 +576,45 @@ public function postSave(EntityStorageControllerInterface $storage_controller, $
   }
 
   /**
+   * @inheritdoc}
+   *
+   * @todo Don't call parent::postLoad() at all because we want to be able to
+   * control the entity load hooks.
+   */
+  public static function postLoad(EntityStorageControllerInterface $storage_controller, array $entities) {
+    $routes = array();
+
+    foreach ($entities as $menu_link) {
+      $menu_link->options = unserialize($menu_link->options);
+      $menu_link->route_parameters = unserialize($menu_link->route_parameters);
+
+      // Use the weight property from the menu link.
+      $menu_link->router_item['weight'] = $menu_link->weight;
+
+      // By default use the menu_name as type.
+      $menu_link->bundle = $menu_link->menu_name;
+
+      // For all links that have an associated route, load the route object now
+      // and save it on the object. That way we avoid a select N+1 problem later.
+      if ($menu_link->route_name) {
+        $routes[$menu_link->id()] = $menu_link->route_name;
+      }
+    }
+
+    // Now mass-load any routes needed and associate them.
+    if ($routes) {
+      $route_objects = \Drupal::service('router.route_provider')->getRoutesByNames($routes);
+      foreach ($routes as $entity_id => $route) {
+        // Not all stored routes will be valid on load.
+        if (isset($route_objects[$route])) {
+          $entities[$entity_id]->setRouteObject($route_objects[$route]);
+        }
+      }
+    }
+    parent::postLoad($storage_controller, $entities);
+  }
+
+  /**
    * {@inheritdoc}
    */
   public static function findRouteNameParameters($link_path) {
diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php
index c7ef831..87b6988 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php
@@ -106,46 +106,6 @@ protected function buildQuery($ids, $revision_id = FALSE) {
   }
 
   /**
-   * Overrides DatabaseStorageController::attachLoad().
-   *
-   * @todo Don't call parent::attachLoad() at all because we want to be able to
-   * control the entity load hooks.
-   */
-  protected function attachLoad(&$menu_links, $load_revision = FALSE) {
-    $routes = array();
-
-    foreach ($menu_links as &$menu_link) {
-      $menu_link->options = unserialize($menu_link->options);
-      $menu_link->route_parameters = unserialize($menu_link->route_parameters);
-
-      // Use the weight property from the menu link.
-      $menu_link->router_item['weight'] = $menu_link->weight;
-
-      // By default use the menu_name as type.
-      $menu_link->bundle = $menu_link->menu_name;
-
-      // For all links that have an associated route, load the route object now
-      // and save it on the object. That way we avoid a select N+1 problem later.
-      if ($menu_link->route_name) {
-        $routes[$menu_link->id()] = $menu_link->route_name;
-      }
-    }
-
-    // Now mass-load any routes needed and associate them.
-    if ($routes) {
-      $route_objects = $this->routeProvider->getRoutesByNames($routes);
-      foreach ($routes as $entity_id => $route) {
-        // Not all stored routes will be valid on load.
-        if (isset($route_objects[$route])) {
-          $menu_links[$entity_id]->setRouteObject($route_objects[$route]);
-        }
-      }
-    }
-
-    parent::attachLoad($menu_links, $load_revision);
-  }
-
-  /**
    * Overrides DatabaseStorageController::save().
    */
   public function save(EntityInterface $entity) {
diff --git a/core/modules/node/lib/Drupal/node/Entity/Node.php b/core/modules/node/lib/Drupal/node/Entity/Node.php
index d7b1f6a..aa18d0e 100644
--- a/core/modules/node/lib/Drupal/node/Entity/Node.php
+++ b/core/modules/node/lib/Drupal/node/Entity/Node.php
@@ -21,7 +21,7 @@
  *   label = @Translation("Content"),
  *   bundle_label = @Translation("Content type"),
  *   controllers = {
- *     "storage" = "Drupal\node\NodeStorageController",
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController",
  *     "view_builder" = "Drupal\node\NodeViewBuilder",
  *     "access" = "Drupal\node\NodeAccessController",
  *     "form" = {
@@ -77,6 +77,16 @@ public function getRevisionId() {
   /**
    * {@inheritdoc}
    */
+  public static function preCreate(EntityStorageControllerInterface $storage_controller, array &$values) {
+    // @todo Handle this through property defaults.
+    if (empty($values['created'])) {
+      $values['created'] = REQUEST_TIME;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function preSave(EntityStorageControllerInterface $storage_controller) {
     parent::preSave($storage_controller);
 
@@ -149,6 +159,13 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr
   /**
    * {@inheritdoc}
    */
+  public static function postDelete(EntityStorageControllerInterface $storage_controller, array $nodes) {
+    \Drupal::service('node.grant_storage')->deleteNodeRecords(array_keys($nodes));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getType() {
     return $this->bundle();
   }
diff --git a/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorage.php b/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorage.php
index 8dcc8f3..9efe421 100644
--- a/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorage.php
+++ b/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorage.php
@@ -230,7 +230,7 @@ public function write(NodeInterface $node, array $grants, $realm = NULL, $delete
    * {@inheritdoc}
    */
   public function delete() {
-    $this->database->delete('node_access')->execute();
+    $this->database->truncate('node_access')->execute();
   }
 
   /**
@@ -256,4 +256,13 @@ public function count() {
     return $this->database->query('SELECT COUNT(*) FROM {node_access}')->fetchField();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteNodeRecords(array $nids) {
+    $this->database->delete('node_access')
+      ->condition('nid', $nids, 'IN')
+      ->execute();
+  }
+
 }
diff --git a/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorageInterface.php b/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorageInterface.php
index 2457b8f..ad45741 100644
--- a/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorageInterface.php
+++ b/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorageInterface.php
@@ -121,4 +121,13 @@ public function access(EntityInterface $node, $operation, $langcode, AccountInte
    */
   public function count();
 
+  /**
+   * Remove the access records belonging to certain nodes.
+   *
+   * @param array $nids
+   *   A list of node IDs. The grant records belonging to these nodes will be
+   *   deleted.
+   */
+  public function deleteNodeRecords(array $nids);
+
 }
diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php
deleted file mode 100644
index 0c3a623..0000000
--- a/core/modules/node/lib/Drupal/node/NodeStorageController.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\node\NodeStorageController.
- */
-
-namespace Drupal\node;
-
-use Drupal\Core\Entity\FieldableDatabaseStorageController;
-use Drupal\Core\Entity\EntityInterface;
-
-/**
- * Controller class for nodes.
- *
- * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding
- * required special handling for node entities.
- */
-class NodeStorageController extends FieldableDatabaseStorageController {
-
-  /**
-   * Overrides Drupal\Core\Entity\DatabaseStorageController::create().
-   */
-  public function create(array $values) {
-    // @todo Handle this through property defaults.
-    if (empty($values['created'])) {
-      $values['created'] = REQUEST_TIME;
-    }
-    return parent::create($values);
-  }
-
-  /**
-   * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad().
-   */
-  protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
-    $queried_entities = $this->mapFromStorageRecords($queried_entities, $load_revision);
-
-    // Create an array of nodes for each content type and pass this to the
-    // object type specific callback. To preserve backward-compatibility we
-    // pass on BC decorators to node-specific hooks, while we pass on the
-    // regular entity objects else.
-    $typed_nodes = array();
-    foreach ($queried_entities as $id => $node) {
-      $typed_nodes[$node->bundle()][$id] = $queried_entities[$id];
-    }
-
-    if ($load_revision) {
-      $this->loadFieldItems($queried_entities, static::FIELD_LOAD_REVISION);
-    }
-    else {
-      $this->loadFieldItems($queried_entities, static::FIELD_LOAD_CURRENT);
-    }
-
-    // Besides the list of nodes, pass one additional argument to
-    // hook_node_load(), containing a list of node types that were loaded.
-    $argument = array_keys($typed_nodes);
-    $this->hookLoadArguments = array($argument);
-
-    // Call hook_entity_load().
-    foreach (\Drupal::moduleHandler()->getImplementations('entity_load') as $module) {
-      $function = $module . '_entity_load';
-      $function($queried_entities, $this->entityType);
-    }
-    // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are
-    // always the queried entities, followed by additional arguments set in
-    // $this->hookLoadArguments.
-    $args = array_merge(array($queried_entities), $this->hookLoadArguments);
-    foreach (\Drupal::moduleHandler()->getImplementations($this->entityType . '_load') as $module) {
-      call_user_func_array($module . '_' . $this->entityType . '_load', $args);
-    }
-  }
-
-  /**
-   * Overrides Drupal\Core\Entity\DatabaseStorageController::postDelete().
-   */
-  protected function postDelete($nodes) {
-    // Delete values from other tables also referencing this node.
-    $ids = array_keys($nodes);
-
-    db_delete('node_access')
-      ->condition('nid', $ids, 'IN')
-      ->execute();
-  }
-
-}
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeLoadHooksTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeLoadHooksTest.php
deleted file mode 100644
index da2df6a..0000000
--- a/core/modules/node/lib/Drupal/node/Tests/NodeLoadHooksTest.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\node\Tests\NodeLoadHooksTest.
- */
-
-namespace Drupal\node\Tests;
-
-/**
- * Tests for the hooks invoked during node_load().
- */
-class NodeLoadHooksTest extends NodeTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('node_test');
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Node load hooks',
-      'description' => 'Test the hooks invoked when a node is being loaded.',
-      'group' => 'Node',
-    );
-  }
-
-  /**
-   * Tests that hook_node_load() is invoked correctly.
-   */
-  function testHookNodeLoad() {
-    // Create some sample articles and pages.
-    $node1 = $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_PUBLISHED));
-    $node2 = $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_PUBLISHED));
-    $node3 = $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_NOT_PUBLISHED));
-    $node4 = $this->drupalCreateNode(array('type' => 'page', 'status' => NODE_NOT_PUBLISHED));
-
-    // Check that when a set of nodes that only contains articles is loaded,
-    // the properties added to the node by node_test_load_node() correctly
-    // reflect the expected values.
-    $nodes = entity_load_multiple_by_properties('node', array('status' => NODE_PUBLISHED));
-    $loaded_node = end($nodes);
-    $this->assertEqual($loaded_node->node_test_loaded_nids, array($node1->id(), $node2->id()), 'hook_node_load() received the correct list of node IDs the first time it was called.');
-    $this->assertEqual($loaded_node->node_test_loaded_types, array('article'), 'hook_node_load() received the correct list of node types the first time it was called.');
-
-    // Now, as part of the same page request, load a set of nodes that contain
-    // both articles and pages, and make sure the parameters passed to
-    // node_test_node_load() are correctly updated.
-    $nodes = entity_load_multiple_by_properties('node', array('status' => NODE_NOT_PUBLISHED));
-    $loaded_node = end($nodes);
-    $this->assertEqual($loaded_node->node_test_loaded_nids, array($node3->id(), $node4->id()), 'hook_node_load() received the correct list of node IDs the second time it was called.');
-    $this->assertEqual($loaded_node->node_test_loaded_types, array('article', 'page'), 'hook_node_load() received the correct list of node types the second time it was called.');
-  }
-}
diff --git a/core/modules/node/node.api.php b/core/modules/node/node.api.php
index 807ee49..299eefa 100644
--- a/core/modules/node/node.api.php
+++ b/core/modules/node/node.api.php
@@ -501,20 +501,23 @@ function hook_node_create(\Drupal\Core\Entity\EntityInterface $node) {
  *
  * @param $nodes
  *   An array of the nodes being loaded, keyed by nid.
- * @param $types
- *   An array containing the node types present in $nodes. Allows for an early
- *   return for modules that only support certain node types.
  *
  * For a detailed usage example, see nodeapi_example.module.
  *
  * @ingroup node_api_hooks
  */
-function hook_node_load($nodes, $types) {
+function hook_node_load($nodes) {
   // Decide whether any of $types are relevant to our purposes.
   $types_we_want_to_process = \Drupal::config('my_types')->get('types');
-  if (count(array_intersect($types_we_want_to_process, $types))) {
+  $nids = array();
+  foreach ($nodes as $node) {
+    if (in_array($node->bundle(), $types_we_want_to_process)) {
+      $nids = $node->id();
+    }
+  }
+  if ($nids) {
     // Gather our extra data for each of these nodes.
-    $result = db_query('SELECT nid, foo FROM {mytable} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes)));
+    $result = db_query('SELECT nid, foo FROM {mytable} WHERE nid IN(:nids)', array(':nids' => $nids));
     // Add our extra data to the node objects.
     foreach ($result as $record) {
       $nodes[$record->nid]->foo = $record->foo;
diff --git a/core/modules/node/tests/modules/node_access_test/node_access_test.module b/core/modules/node/tests/modules/node_access_test/node_access_test.module
index 923bcb0..24b7947 100644
--- a/core/modules/node/tests/modules/node_access_test/node_access_test.module
+++ b/core/modules/node/tests/modules/node_access_test/node_access_test.module
@@ -111,7 +111,7 @@ function node_access_test_form_node_form_alter(&$form, $form_state) {
 /**
  * Implements hook_node_load().
  */
-function node_access_test_node_load($nodes, $types) {
+function node_access_test_node_load($nodes) {
   $result = db_query('SELECT nid, private FROM {node_access_test} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes)));
   foreach ($result as $record) {
     $nodes[$record->nid]->private = $record->private;
diff --git a/core/modules/node/tests/modules/node_test/node_test.module b/core/modules/node/tests/modules/node_test/node_test.module
index 450f703..1c067fc 100644
--- a/core/modules/node/tests/modules/node_test/node_test.module
+++ b/core/modules/node/tests/modules/node_test/node_test.module
@@ -13,22 +13,6 @@
 use Drupal\node\NodeInterface;
 
 /**
- * Implements hook_node_load().
- */
-function node_test_node_load($nodes, $types) {
-  // Add properties to each loaded node which record the parameters that were
-  // passed in to this function, so the tests can check that (a) this hook was
-  // called, and (b) the parameters were what we expected them to be.
-  $nids = array_keys($nodes);
-  ksort($nids);
-  sort($types);
-  foreach ($nodes as $node) {
-    $node->node_test_loaded_nids = $nids;
-    $node->node_test_loaded_types = $types;
-  }
-}
-
-/**
  * Implements hook_node_view().
  */
 function node_test_node_view(EntityInterface $node, EntityDisplay $display, $view_mode) {
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php b/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php
index d826f70..f8771e2 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php
@@ -101,6 +101,19 @@ public function postCreate(EntityStorageControllerInterface $storage_controller)
   /**
    * {@inheritdoc}
    */
+  public static function postLoad(EntityStorageControllerInterface $storage_controller, array $entities) {
+    foreach ($entities as $id => $entity) {
+      $links = menu_load_links('shortcut-' . $id);
+      foreach ($links as $menu_link) {
+        $entity->links[$menu_link->uuid()] = $menu_link;
+      }
+    }
+    parent::postLoad($storage_controller, $entities);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function preSave(EntityStorageControllerInterface $storage_controller) {
     parent::preSave($storage_controller);
 
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetStorageController.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetStorageController.php
index 2f17850..7c0dee5 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetStorageController.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetStorageController.php
@@ -16,20 +16,6 @@
 class ShortcutSetStorageController extends ConfigStorageController implements ShortcutSetStorageControllerInterface {
 
   /**
-   * Overrides \Drupal\config\ConfigStorageController::attachLoad().
-   */
-  protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
-    parent::attachLoad($queried_entities, $revision_id);
-
-    foreach ($queried_entities as $id => $entity) {
-      $links = menu_load_links('shortcut-' . $id);
-      foreach ($links as $menu_link) {
-        $entity->links[$menu_link->uuid()] = $menu_link;
-      }
-    }
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function deleteAssignedShortcutSets(ShortcutSetInterface $entity) {
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
index d776c85..084be1f 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Language\Language;
 
 /**
@@ -19,7 +20,7 @@
  *   id = "entity_test",
  *   label = @Translation("Test entity"),
  *   controllers = {
- *     "storage" = "Drupal\entity_test\EntityTestStorageController",
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController",
  *     "list" = "Drupal\entity_test\EntityTestListController",
  *     "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
  *     "access" = "Drupal\entity_test\EntityTestAccessController",
@@ -95,6 +96,15 @@ protected function init() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public static function preCreate(EntityStorageControllerInterface $storage_controller, array &$values) {
+    if (empty($values['type'])) {
+      $values['type'] = $storage_controller->entityType();
+    }
+  }
+
+  /**
    * Overrides Drupal\entity\Entity::label().
    */
   public function label($langcode = NULL) {
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php
index 48d345e..642439a 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php
@@ -18,7 +18,7 @@
  *   id = "entity_test_cache",
  *   label = @Translation("Test entity with field cache"),
  *   controllers = {
- *     "storage" = "Drupal\entity_test\EntityTestStorageController",
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController",
  *     "access" = "Drupal\entity_test\EntityTestAccessController",
  *     "form" = {
  *       "default" = "Drupal\entity_test\EntityTestFormController"
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestDefaultAccess.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestDefaultAccess.php
index 572dcbb..084f062 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestDefaultAccess.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestDefaultAccess.php
@@ -17,7 +17,7 @@
  *   id = "entity_test_default_access",
  *   label = @Translation("Test entity with default access"),
  *   controllers = {
- *     "storage" = "Drupal\entity_test\EntityTestStorageController"
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController"
  *   },
  *   base_table = "entity_test",
  *   entity_keys = {
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php
index 13041a4..e09743e 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php
@@ -17,7 +17,7 @@
  *   id = "entity_test_label",
  *   label = @Translation("Entity Test label"),
  *   controllers = {
- *     "storage" = "Drupal\entity_test\EntityTestStorageController",
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController",
  *     "view_builder" = "Drupal\entity_test\EntityTestViewBuilder"
  *   },
  *   base_table = "entity_test",
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php
index 92012a3..b99ff71 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php
@@ -17,7 +17,7 @@
  *   id = "entity_test_label_callback",
  *   label = @Translation("Entity test label callback"),
  *   controllers = {
- *     "storage" = "Drupal\entity_test\EntityTestStorageController"
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController"
  *   },
  *   field_cache = FALSE,
  *   base_table = "entity_test",
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
index e4e0f9c..af14fdc 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
@@ -18,7 +18,7 @@
  *   id = "entity_test_mul",
  *   label = @Translation("Test entity - data table"),
  *   controllers = {
- *     "storage" = "Drupal\entity_test\EntityTestStorageController",
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController",
  *     "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
  *     "access" = "Drupal\entity_test\EntityTestAccessController",
  *     "form" = {
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php
index 25887a5..e693bcd 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php
@@ -18,7 +18,7 @@
  *   id = "entity_test_mulrev",
  *   label = @Translation("Test entity - revisions and data table"),
  *   controllers = {
- *     "storage" = "Drupal\entity_test\EntityTestStorageController",
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController",
  *     "access" = "Drupal\entity_test\EntityTestAccessController",
  *     "form" = {
  *       "default" = "Drupal\entity_test\EntityTestFormController"
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestNoLabel.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestNoLabel.php
index a227a34..63db9d6 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestNoLabel.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestNoLabel.php
@@ -17,7 +17,7 @@
  *   id = "entity_test_no_label",
  *   label = @Translation("Entity Test without label"),
  *   controllers = {
- *     "storage" = "Drupal\entity_test\EntityTestStorageController"
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController"
  *   },
  *   field_cache = FALSE,
  *   base_table = "entity_test",
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php
index fb6d42c..a695b9d 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php
@@ -18,7 +18,7 @@
  *   id = "entity_test_rev",
  *   label = @Translation("Test entity - revisions"),
  *   controllers = {
- *     "storage" = "Drupal\entity_test\EntityTestStorageController",
+ *     "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController",
  *     "access" = "Drupal\entity_test\EntityTestAccessController",
  *     "form" = {
  *       "default" = "Drupal\entity_test\EntityTestFormController"
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php
deleted file mode 100644
index a348fc6..0000000
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\entity_test\EntityTestStorageController.
- */
-
-namespace Drupal\entity_test;
-
-use Drupal\Core\Entity\FieldableDatabaseStorageController;
-
-/**
- * Defines the controller class for the test entity.
- *
- * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding
- * required special handling for test entities.
- */
-class EntityTestStorageController extends FieldableDatabaseStorageController {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function create(array $values) {
-    if (empty($values['type'])) {
-      $values['type'] = $this->entityType;
-    }
-    return parent::create($values);
-  }
-
-}
diff --git a/core/modules/user/lib/Drupal/user/Entity/Role.php b/core/modules/user/lib/Drupal/user/Entity/Role.php
index d58a358..aad4ec9 100644
--- a/core/modules/user/lib/Drupal/user/Entity/Role.php
+++ b/core/modules/user/lib/Drupal/user/Entity/Role.php
@@ -111,6 +111,16 @@ public function revokePermission($permission) {
   /**
    * {@inheritdoc}
    */
+  public static function postLoad(EntityStorageControllerInterface $storage_controller, array $entities) {
+    parent::postLoad($storage_controller, $entities);
+    // Sort the queried roles by their weight.
+    // See \Drupal\Core\Config\Entity\ConfigEntityBase::sort().
+    uasort($queried_entities, array(__CLASS__, 'sort'));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function preSave(EntityStorageControllerInterface $storage_controller) {
     parent::preSave($storage_controller);
 
diff --git a/core/modules/user/lib/Drupal/user/RoleStorageController.php b/core/modules/user/lib/Drupal/user/RoleStorageController.php
index 03937a6..0c6fbfe 100644
--- a/core/modules/user/lib/Drupal/user/RoleStorageController.php
+++ b/core/modules/user/lib/Drupal/user/RoleStorageController.php
@@ -24,15 +24,4 @@ public function deleteRoleReferences(array $rids) {
       ->execute();
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
-    // Sort the queried roles by their weight.
-    // See \Drupal\Core\Config\Entity\ConfigEntityBase::sort().
-    uasort($queried_entities, array($this->entityInfo['class'], 'sort'));
-
-    parent::attachLoad($queried_entities, $revision_id);
-  }
-
 }
diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php
index 48e8206..c2f16f3 100644
--- a/core/modules/user/lib/Drupal/user/UserStorageController.php
+++ b/core/modules/user/lib/Drupal/user/UserStorageController.php
@@ -79,9 +79,9 @@ public static function createInstance(ContainerInterface $container, $entity_typ
   }
 
   /**
-   * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad().
+   * Overrides Drupal\Core\Entity\DatabaseStorageController::postLoad().
    */
-  function attachLoad(&$queried_users, $load_revision = FALSE) {
+  function postLoad(array &$queried_users, $revision_id = FALSE) {
     foreach ($queried_users as $key => $record) {
       $queried_users[$key]->roles = array();
       if ($record->uid) {
@@ -95,9 +95,9 @@ function attachLoad(&$queried_users, $load_revision = FALSE) {
     // Add any additional roles from the database.
     $this->addRoles($queried_users);
 
-    // Call the default attachLoad() method. This will add fields and call
+    // Call the default postLoad() method. This will add fields and call
     // hook_user_load().
-    parent::attachLoad($queried_users, $load_revision);
+    parent::postLoad($queried_users, $revision_id);
   }
 
   /**
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 8dfae6a..c4a4ce3 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1787,7 +1787,7 @@ function user_form_process_password_confirm($element) {
  *   \Drupal\node\NodeViewBuilder::buildContent(). Update code that
  *   depends on these properties.
  */
-function user_node_load($nodes, $types) {
+function user_node_load($nodes) {
   // Build an array of all uids for node authors, keyed by nid.
   $uids = array();
   foreach ($nodes as $nid => $node) {
diff --git a/core/modules/views/lib/Drupal/views/Entity/View.php b/core/modules/views/lib/Drupal/views/Entity/View.php
index 1420ed8..3af5a1e 100644
--- a/core/modules/views/lib/Drupal/views/Entity/View.php
+++ b/core/modules/views/lib/Drupal/views/Entity/View.php
@@ -287,6 +287,16 @@ public function postSave(EntityStorageControllerInterface $storage_controller, $
   /**
    * {@inheritdoc}
    */
+  public static function postLoad(EntityStorageControllerInterface $storage_controller, array $entities) {
+    parent::postLoad($storage_controller, $entities);
+    foreach ($entities as $entity) {
+      $entity->mergeDefaultDisplaysOptions();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public static function preCreate(EntityStorageControllerInterface $storage_controller, array &$values) {
     parent::preCreate($storage_controller, $values);
 
diff --git a/core/modules/views/lib/Drupal/views/ViewStorageController.php b/core/modules/views/lib/Drupal/views/ViewStorageController.php
index 087d34e..a418fb1 100644
--- a/core/modules/views/lib/Drupal/views/ViewStorageController.php
+++ b/core/modules/views/lib/Drupal/views/ViewStorageController.php
@@ -30,16 +30,4 @@ public function loadMultiple(array $ids = NULL) {
     });
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
-    foreach ($queried_entities as $entity) {
-      $entity->mergeDefaultDisplaysOptions();
-    }
-
-    parent::attachLoad($queried_entities, $revision_id);
-  }
-
-
 }
